/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1991, 1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/errno.h>
#include <setjmp.h>
#include <sys/tiuser.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <rpc/rpc_msg.h>
#include <rpc/pmap_prot.h>
#include "snoop.h"
/*
* Number of bytes to display from a string (address, netid, etc.).
*/
#define MAXSTRINGLEN 64
extern char *dlc_header;
extern jmp_buf xdr_err;
static void interpret_pmap_2(int, int, int, int, int, char *, int);
static void interpret_pmap_4(int, int, int, int, int, char *, int);
static void stash_callit(ulong_t, int, int, int, int);
void
interpret_pmap(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
switch (vers) {
case 2: interpret_pmap_2(flags, type, xid, vers, proc, data, len);
break;
/* Version 3 is a subset of version 4 */
case 3:
case 4: interpret_pmap_4(flags, type, xid, vers, proc, data, len);
break;
}
}
void show_pmap();
char *sum_pmaplist();
void show_pmaplist();
static char *procnames_short_2[] = {
"Null", /* 0 */
"SET", /* 1 */
"UNSET", /* 2 */
"GETPORT", /* 3 */
"DUMP", /* 4 */
"CALLIT", /* 5 */
};
static char *procnames_long_2[] = {
"Null procedure", /* 0 */
"Set port", /* 1 */
"Unset port", /* 2 */
"Get port number", /* 3 */
"Dump the mappings", /* 4 */
"Indirect call", /* 5 */
};
#define MAXPROC_2 5
void
interpret_pmap_2(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
char *line;
unsigned port, proto;
unsigned iprog, ivers, iproc, ilen;
extern int pi_frame;
struct cache_struct *x, *find_callit();
int trailer_done = 0;
if (proc < 0 || proc > MAXPROC_2)
return;
if (proc == PMAPPROC_CALLIT) {
if (type == CALL) {
iprog = getxdr_u_long();
ivers = getxdr_u_long();
iproc = getxdr_u_long();
stash_callit(xid, pi_frame, iprog, ivers, iproc);
} else {
x = find_callit(xid);
}
}
if (flags & F_SUM) {
if (setjmp(xdr_err)) {
return;
}
line = get_sum_line();
if (type == CALL) {
(void) sprintf(line, "PORTMAP C %s",
procnames_short_2[proc]);
line += strlen(line);
switch (proc) {
case PMAPPROC_GETPORT:
iprog = getxdr_u_long();
ivers = getxdr_u_long();
proto = getxdr_u_long();
(void) sprintf(line,
" prog=%d (%s) vers=%d proto=%s",
iprog, nameof_prog(iprog),
ivers,
getproto(proto));
break;
case PMAPPROC_CALLIT:
(void) sprintf(line,
" prog=%s vers=%d proc=%d",
nameof_prog(iprog),
ivers, iproc);
if (flags & F_ALLSUM) {
(void) getxdr_u_long(); /* length */
data += 16; /* prog+ver+proc+len */
len -= 16;
protoprint(flags, type, xid,
iprog, ivers, iproc,
data, len);
}
break;
default:
break;
}
check_retransmit(line, xid);
} else {
(void) sprintf(line, "PORTMAP R %s ",
procnames_short_2[proc]);
line += strlen(line);
switch (proc) {
case PMAPPROC_GETPORT:
port = getxdr_u_long();
(void) sprintf(line, "port=%d", port);
break;
case PMAPPROC_DUMP:
(void) sprintf(line, "%s", sum_pmaplist());
break;
case PMAPPROC_CALLIT:
port = getxdr_u_long();
ilen = getxdr_u_long();
(void) sprintf(line, "port=%d len=%d",
port, ilen);
if (flags & F_ALLSUM && x != NULL) {
data += 8; /* port+len */
len -= 8;
protoprint(flags, type, xid,
x->xid_prog,
x->xid_vers,
x->xid_proc,
data, len);
}
break;
default:
break;
}
}
}
if (flags & F_DTAIL) {
show_header("PMAP: ", "Portmapper", len);
show_space();
if (setjmp(xdr_err)) {
return;
}
(void) sprintf(get_line(0, 0),
"Proc = %d (%s)",
proc, procnames_long_2[proc]);
if (type == CALL) {
switch (proc) {
case PMAPPROC_NULL:
case PMAPPROC_SET:
case PMAPPROC_UNSET:
break;
case PMAPPROC_GETPORT:
iprog = getxdr_u_long();
(void) sprintf(get_line(0, 0),
"Program = %d (%s)",
iprog, nameof_prog(iprog));
(void) showxdr_u_long("Version = %d");
proto = getxdr_u_long();
(void) sprintf(get_line(0, 0),
"Protocol = %d (%s)",
proto, getproto(proto));
break;
case PMAPPROC_DUMP:
break;
case PMAPPROC_CALLIT:
(void) sprintf(get_line(0, 0),
"Program = %d (%s)",
iprog, nameof_prog(iprog));
(void) sprintf(get_line(0, 0),
"Version = %d", ivers);
(void) sprintf(get_line(0, 0),
"Proc = %d", iproc);
(void) showxdr_u_long("Callit data = %d bytes");
show_trailer();
trailer_done = 1;
data += 16; /* prog+ver+proc+len */
len -= 16;
protoprint(flags, type, xid,
iprog, ivers, iproc,
data, len);
break;
}
} else {
switch (proc) {
case PMAPPROC_NULL:
case PMAPPROC_SET:
case PMAPPROC_UNSET:
break;
case PMAPPROC_GETPORT:
(void) showxdr_u_long("Port = %d");
break;
case PMAPPROC_DUMP:
show_pmaplist();
break;
case PMAPPROC_CALLIT:
(void) showxdr_u_long("Port = %d");
(void) showxdr_u_long("Length = %d bytes");
show_trailer();
trailer_done = 1;
if (x != NULL) {
protoprint(flags, type, xid,
x->xid_prog,
x->xid_vers,
x->xid_proc,
data, len);
}
break;
}
}
if (!trailer_done)
show_trailer();
}
}
char *
sum_pmaplist()
{
int maps = 0;
static char buff[16];
if (setjmp(xdr_err)) {
(void) sprintf(buff, "%d+ map(s) found", maps);
return (buff);
}
while (getxdr_u_long()) {
(void) getxdr_u_long(); /* program */
(void) getxdr_u_long(); /* version */
(void) getxdr_u_long(); /* protocol */
(void) getxdr_u_long(); /* port */
maps++;
}
(void) sprintf(buff, "%d map(s) found", maps);
return (buff);
}
void
show_pmaplist()
{
unsigned prog, vers, proto, port;
int maps = 0;
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ maps. (Frame is incomplete)",
maps);
return;
}
(void) sprintf(get_line(0, 0), " Program Version Protocol Port");
while (getxdr_u_long()) {
prog = getxdr_u_long();
vers = getxdr_u_long();
proto = getxdr_u_long();
port = getxdr_u_long();
(void) sprintf(get_line(0, 0),
"%8d%8d%9d%7d %s",
prog, vers, proto, port, nameof_prog(prog));
maps++;
}
(void) sprintf(get_line(0, 0), " %d maps", maps);
}
/*
* ******************************************
*/
char *sum_rpcblist();
void show_rpcblist();
char *sum_rpcb_entry_list();
void show_rpcb_entry_list();
static char *procnames_short_4[] = {
/*
* version 3 and 4 procs
*/
"Null", /* 0 */
"SET", /* 1 */
"UNSET", /* 2 */
"GETADDR", /* 3 */
"DUMP", /* 4 */
"BCAST", /* 5 */
"GETTIME", /* 6 */
"UADDR2TADDR", /* 7 */
"TADDR2UADDR", /* 8 */
/*
* version 4 procs only
*/
"GETVERSADDR", /* 9 */
"INDIRECT", /* 10 */
"GETADDRLIST", /* 11 */
"GETSTAT", /* 12 */
};
static char *procnames_long_4[] = {
/*
* version 3 and 4 procs
*/
"Null procedure", /* 0 */
"Set address", /* 1 */
"Unset address", /* 2 */
"Get address", /* 3 */
"Dump the mappings", /* 4 */
"Broadcast call (no error)", /* 5 */
"Get the time", /* 6 */
"Universal to transport address", /* 7 */
"Transport to universal address", /* 8 */
/*
* version 4 procs only
*/
"Get address of specific version", /* 9 */
"Indirect call (return error)", /* 10 */
"Return addresses of prog/vers", /* 11 */
"Get statistics", /* 12 */
};
#define MAXPROC_3 8
#define MAXPROC_4 12
#define RPCBPROC_NULL 0
void
interpret_pmap_4(flags, type, xid, vers, proc, data, len)
int flags, type, xid, vers, proc;
char *data;
int len;
{
char *line;
unsigned prog, ver;
char buff1[MAXSTRINGLEN + 1];
int iprog, ivers, iproc, ilen;
extern int pi_frame;
struct cache_struct *x, *find_callit();
int trailer_done = 0;
if (proc < 0 || proc > MAXPROC_4 || (vers == 3 && proc > MAXPROC_3))
return;
if (proc == RPCBPROC_BCAST || proc == RPCBPROC_INDIRECT) {
if (type == CALL) {
iprog = getxdr_u_long();
ivers = getxdr_u_long();
iproc = getxdr_u_long();
stash_callit(xid, pi_frame,
iprog, ivers, iproc);
} else {
x = find_callit(xid);
}
}
if (flags & F_SUM) {
if (setjmp(xdr_err)) {
return;
}
line = get_sum_line();
if (type == CALL) {
(void) sprintf(line,
"RPCBIND C %s",
procnames_short_4[proc]);
line += strlen(line);
switch (proc) {
case RPCBPROC_SET:
case RPCBPROC_UNSET:
case RPCBPROC_GETADDR:
case RPCBPROC_GETVERSADDR:
case RPCBPROC_GETADDRLIST:
prog = getxdr_u_long();
ver = getxdr_u_long();
(void) sprintf(line,
" prog=%d (%s) vers=%d",
prog, nameof_prog(prog),
ver);
break;
case RPCBPROC_BCAST:
case RPCBPROC_INDIRECT:
(void) sprintf(line,
" prog=%s vers=%d proc=%d",
nameof_prog(iprog),
ivers, iproc);
if (flags & F_ALLSUM) {
(void) getxdr_u_long(); /* length */
data += 16; /* prog+ver+proc+len */
len -= 16;
protoprint(flags, type, xid,
iprog, ivers, iproc,
data, len);
}
break;
default:
break;
}
check_retransmit(line, xid);
} else {
int pos;
(void) sprintf(line, "RPCBIND R %s ",
procnames_short_4[proc]);
line += strlen(line);
switch (proc) {
case RPCBPROC_GETADDR:
case RPCBPROC_TADDR2UADDR:
case RPCBPROC_GETVERSADDR:
(void) getxdr_string(buff1, MAXSTRINGLEN);
(void) sprintf(line,
" Uaddr=%s",
buff1);
break;
case RPCBPROC_BCAST:
case RPCBPROC_INDIRECT:
pos = getxdr_pos();
(void) getxdr_string(buff1, MAXSTRINGLEN);
ilen = getxdr_u_long();
(void) sprintf(line, "Uaddr=%s len=%d",
buff1, ilen);
if (flags & F_ALLSUM && x != NULL) {
pos = getxdr_pos() - pos;
data += pos; /* uaddr+len */
len -= pos;
protoprint(flags, type, xid,
x->xid_prog,
x->xid_vers,
x->xid_proc,
data, len);
}
break;
case RPCBPROC_DUMP:
(void) sprintf(line, "%s",
sum_rpcblist());
break;
case RPCBPROC_GETTIME:
{
time_t sec = getxdr_long();
struct tm *tmp = gmtime(&sec);
(void) strftime(line, MAXLINE,
"%d-%h-%y %T GMT", tmp);
}
break;
case RPCBPROC_GETADDRLIST:
(void) sprintf(line, "%s",
sum_rpcb_entry_list());
break;
default:
break;
}
}
}
if (flags & F_DTAIL) {
show_header("RPCB: ", "RPC Bind", len);
show_space();
if (setjmp(xdr_err)) {
return;
}
(void) sprintf(get_line(0, 0),
"Proc = %d (%s)",
proc, procnames_long_4[proc]);
if (type == CALL) {
switch (proc) {
case RPCBPROC_NULL:
break;
case RPCBPROC_SET:
case RPCBPROC_UNSET:
case RPCBPROC_GETADDR:
case RPCBPROC_GETVERSADDR:
case RPCBPROC_GETADDRLIST:
(void) showxdr_u_long("Program = %d");
(void) showxdr_u_long("Version = %d");
(void) showxdr_string(64, "Netid = %s");
break;
case RPCBPROC_DUMP:
break;
case RPCBPROC_BCAST:
case RPCBPROC_INDIRECT:
(void) sprintf(get_line(0, 0),
"Program = %d (%s)",
iprog, nameof_prog(iprog));
(void) sprintf(get_line(0, 0),
"Version = %d", ivers);
(void) sprintf(get_line(0, 0),
"Proc = %d", iproc);
(void) showxdr_u_long(
"Callit data = %d bytes");
show_trailer();
trailer_done = 1;
data += 16; /* prog+ver+proc+len */
len -= 16;
protoprint(flags, type, xid,
iprog, ivers, iproc,
data, len);
break;
case RPCBPROC_GETTIME:
break;
case RPCBPROC_UADDR2TADDR:
case RPCBPROC_TADDR2UADDR:
break;
}
} else {
switch (proc) {
case RPCBPROC_NULL:
case RPCBPROC_SET:
case RPCBPROC_UNSET:
break;
case RPCBPROC_GETADDR:
case RPCBPROC_TADDR2UADDR:
case RPCBPROC_GETVERSADDR:
(void) showxdr_string(64, "Uaddr = %s");
break;
case RPCBPROC_DUMP:
show_rpcblist();
break;
case RPCBPROC_BCAST:
case RPCBPROC_INDIRECT:
(void) showxdr_string(64, "Uaddr = %s");
(void) showxdr_u_long("Length = %d bytes");
show_trailer();
trailer_done = 1;
if (x != NULL) {
protoprint(flags, type, xid,
x->xid_prog,
x->xid_vers,
x->xid_proc,
data, len);
}
break;
case RPCBPROC_GETTIME:
{
int pos = getxdr_pos();
time_t sec = getxdr_long();
struct tm *tmp = gmtime(&sec);
(void) strftime(get_line(pos,
getxdr_pos()), MAXLINE,
"Time = %d-%h-%y %T GMT", tmp);
}
break;
case RPCBPROC_UADDR2TADDR:
break;
case RPCBPROC_GETADDRLIST:
show_rpcb_entry_list();
break;
}
}
if (!trailer_done)
show_trailer();
}
}
char *
sum_rpcblist()
{
int maps = 0;
static char buff[MAXSTRINGLEN + 1];
if (setjmp(xdr_err)) {
(void) sprintf(buff, "%d+ map(s) found", maps);
return (buff);
}
while (getxdr_u_long()) {
(void) getxdr_u_long(); /* program */
(void) getxdr_u_long(); /* version */
(void) getxdr_string(buff, MAXSTRINGLEN); /* netid */
(void) getxdr_string(buff, MAXSTRINGLEN); /* uaddr */
(void) getxdr_string(buff, MAXSTRINGLEN); /* owner */
maps++;
}
(void) sprintf(buff, "%d map(s) found", maps);
return (buff);
}
void
show_rpcblist()
{
unsigned prog, vers;
char netid[MAXSTRINGLEN + 1], uaddr[MAXSTRINGLEN + 1];
char owner[MAXSTRINGLEN + 1];
int maps = 0;
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ maps. (Frame is incomplete)",
maps);
return;
}
show_space();
(void) sprintf(get_line(0, 0),
" Program Vers Netid Uaddr Owner");
while (getxdr_u_long()) {
prog = getxdr_u_long();
vers = getxdr_u_long();
(void) getxdr_string(netid, MAXSTRINGLEN);
(void) getxdr_string(uaddr, MAXSTRINGLEN);
(void) getxdr_string(owner, MAXSTRINGLEN);
(void) sprintf(get_line(0, 0),
"%8d%5d %-12s %-18s %-10s (%s)",
prog, vers,
netid, uaddr, owner,
nameof_prog(prog));
maps++;
}
(void) sprintf(get_line(0, 0), " (%d maps)", maps);
}
char *
sum_rpcb_entry_list()
{
int maps = 0;
static char buff[MAXSTRINGLEN + 1];
if (setjmp(xdr_err)) {
(void) sprintf(buff, "%d+ map(s) found", maps);
return (buff);
}
while (getxdr_u_long()) {
(void) getxdr_string(buff, MAXSTRINGLEN); /* maddr */
(void) getxdr_string(buff, MAXSTRINGLEN); /* nc_netid */
(void) getxdr_u_long(); /* nc_semantics */
(void) getxdr_string(buff, MAXSTRINGLEN); /* nc_protofmly */
(void) getxdr_string(buff, MAXSTRINGLEN); /* nc_proto */
maps++;
}
(void) sprintf(buff, "%d map(s) found", maps);
return (buff);
}
char *semantics_strs[] = {"", "CLTS", "COTS", "COTS-ORD", "RAW"};
void
show_rpcb_entry_list()
{
char maddr[MAXSTRINGLEN + 1], netid[MAXSTRINGLEN + 1];
char protofmly[MAXSTRINGLEN + 1], proto[MAXSTRINGLEN + 1];
unsigned sem;
int maps = 0;
if (setjmp(xdr_err)) {
(void) sprintf(get_line(0, 0),
" %d+ maps. (Frame is incomplete)",
maps);
return;
}
show_space();
(void) sprintf(get_line(0, 0),
" Maddr Netid Semantics Protofmly Proto");
while (getxdr_u_long()) {
(void) getxdr_string(maddr, MAXSTRINGLEN);
(void) getxdr_string(netid, MAXSTRINGLEN);
sem = getxdr_u_long();
(void) getxdr_string(protofmly, MAXSTRINGLEN);
(void) getxdr_string(proto, MAXSTRINGLEN);
(void) sprintf(get_line(0, 0),
"%-12s %-12s %-8s %-8s %-8s",
maddr, netid,
semantics_strs[sem],
protofmly, proto);
maps++;
}
(void) sprintf(get_line(0, 0), " (%d maps)", maps);
}
#define CXID_CACHE_SIZE 16
struct cache_struct cxid_cache[CXID_CACHE_SIZE];
struct cache_struct *cxcpfirst = &cxid_cache[0];
struct cache_struct *cxcp = &cxid_cache[0];
struct cache_struct *cxcplast = &cxid_cache[CXID_CACHE_SIZE - 1];
struct cache_struct *
find_callit(xid)
ulong_t xid;
{
struct cache_struct *x;
for (x = cxcp; x >= cxcpfirst; x--)
if (x->xid_num == xid)
return (x);
for (x = cxcplast; x > cxcp; x--)
if (x->xid_num == xid)
return (x);
return (NULL);
}
static void
stash_callit(xid, frame, prog, vers, proc)
ulong_t xid;
int frame, prog, vers, proc;
{
struct cache_struct *x;
x = find_callit(xid);
if (x == NULL) {
x = cxcp++;
if (cxcp > cxcplast)
cxcp = cxcpfirst;
x->xid_num = xid;
x->xid_frame = frame;
}
x->xid_prog = prog;
x->xid_vers = vers;
x->xid_proc = proc;
}