#include "mt.h"
#include "rpc_mt.h"
#include <stdio.h>
#include <sys/types.h>
#include <rpc/rpc.h>
#include <rpc/nettype.h>
#include <sys/param.h>
#include <sys/mkdev.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <sys/resource.h>
#include <netconfig.h>
#include <malloc.h>
#include <syslog.h>
#include <string.h>
#include <sys/systeminfo.h>
#include <netdir.h>
#include <netdb.h>
struct handle {
NCONF_HANDLE *nhandle;
int nflag;
int nettype;
};
struct _rpcnettype {
const char *name;
const int type;
} _rpctypelist[] = {
"netpath", _RPC_NETPATH,
"visible", _RPC_VISIBLE,
"circuit_v", _RPC_CIRCUIT_V,
"datagram_v", _RPC_DATAGRAM_V,
"circuit_n", _RPC_CIRCUIT_N,
"datagram_n", _RPC_DATAGRAM_N,
"tcp", _RPC_TCP,
"udp", _RPC_UDP,
"local", _RPC_LOCAL,
"door", _RPC_DOOR,
"door_local", _RPC_DOOR_LOCAL,
"door_netpath", _RPC_DOOR_NETPATH,
0, _RPC_NONE
};
int
__rpc_dtbsize(void)
{
static int tbsize;
struct rlimit rl;
if (tbsize)
return (tbsize);
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
tbsize = rl.rlim_max;
if (tbsize > FD_SETSIZE)
tbsize = FD_SETSIZE;
return (tbsize);
}
return (32);
}
uint_t
__rpc_get_t_size(
t_scalar_t size,
t_scalar_t bufsize)
{
if (bufsize == -2)
return ((uint_t)0);
if (size == 0) {
if ((bufsize == -1) || (bufsize == 0)) {
return ((uint_t)RPC_MAXDATASIZE);
}
return ((uint_t)bufsize);
}
if ((bufsize == -1) || (bufsize == 0))
return ((uint_t)size);
return (size > bufsize ? (uint_t)bufsize : (uint_t)size);
}
uint_t
__rpc_get_a_size(
t_scalar_t size)
{
if (size >= 0)
return ((uint_t)size);
if (size <= -2)
return ((uint_t)0);
return ((uint_t)RPC_MAXADDRSIZE);
}
static int
getnettype(const char *nettype)
{
int i;
if ((nettype == NULL) || (nettype[0] == '\0'))
return (_RPC_NETPATH);
for (i = 0; _rpctypelist[i].name; i++)
if (strcasecmp(nettype, _rpctypelist[i].name) == 0)
return (_rpctypelist[i].type);
return (_rpctypelist[i].type);
}
struct netconfig *
__rpc_getconfip(char *nettype)
{
char *netid;
char *netid_tcp;
char *netid_udp;
static char *netid_tcp_main = NULL;
static char *netid_udp_main = NULL;
static pthread_key_t tcp_key = PTHREAD_ONCE_KEY_NP;
static pthread_key_t udp_key = PTHREAD_ONCE_KEY_NP;
int main_thread;
if ((main_thread = thr_main())) {
netid_udp = netid_udp_main;
netid_tcp = netid_tcp_main;
} else {
(void) pthread_key_create_once_np(&tcp_key, free);
netid_tcp = pthread_getspecific(tcp_key);
(void) pthread_key_create_once_np(&udp_key, free);
netid_udp = pthread_getspecific(udp_key);
}
if (!netid_udp && !netid_tcp) {
struct netconfig *nconf;
void *confighandle;
if (!(confighandle = setnetconfig()))
return (NULL);
while (nconf = getnetconfig(confighandle)) {
if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
netid_tcp = strdup(nconf->nc_netid);
if (netid_tcp == NULL) {
syslog(LOG_ERR,
"__rpc_getconfip : "
"strdup failed");
return (NULL);
}
if (main_thread)
netid_tcp_main = netid_tcp;
else
(void) pthread_setspecific(
tcp_key,
(void *)netid_tcp);
} else
if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
netid_udp = strdup(nconf->nc_netid);
if (netid_udp == NULL) {
syslog(LOG_ERR,
"__rpc_getconfip : "
"strdup failed");
return (NULL);
}
if (main_thread)
netid_udp_main = netid_udp;
else
(void) pthread_setspecific(
udp_key,
(void *)netid_udp);
}
}
}
(void) endnetconfig(confighandle);
}
if (strcmp(nettype, "udp") == 0)
netid = netid_udp;
else if (strcmp(nettype, "tcp") == 0)
netid = netid_tcp;
else
return (NULL);
if ((netid == NULL) || (netid[0] == '\0'))
return (NULL);
return (getnetconfigent(netid));
}
void *
__rpc_setconf(char *nettype)
{
struct handle *handle;
handle = malloc(sizeof (struct handle));
if (handle == NULL)
return (NULL);
switch (handle->nettype = getnettype(nettype)) {
case _RPC_DOOR_NETPATH:
case _RPC_NETPATH:
case _RPC_CIRCUIT_N:
case _RPC_DATAGRAM_N:
if (!(handle->nhandle = setnetpath())) {
free(handle);
return (NULL);
}
handle->nflag = TRUE;
break;
case _RPC_VISIBLE:
case _RPC_CIRCUIT_V:
case _RPC_DATAGRAM_V:
case _RPC_TCP:
case _RPC_UDP:
case _RPC_LOCAL:
case _RPC_DOOR_LOCAL:
if (!(handle->nhandle = setnetconfig())) {
free(handle);
return (NULL);
}
handle->nflag = FALSE;
break;
default:
free(handle);
return (NULL);
}
return (handle);
}
struct netconfig *
__rpc_getconf(void *vhandle)
{
struct handle *handle;
struct netconfig *nconf;
handle = (struct handle *)vhandle;
if (handle == NULL)
return (NULL);
for (;;) {
if (handle->nflag)
nconf = getnetpath(handle->nhandle);
else
nconf = getnetconfig(handle->nhandle);
if (nconf == NULL)
break;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
continue;
switch (handle->nettype) {
case _RPC_VISIBLE:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
case _RPC_DOOR_NETPATH:
case _RPC_NETPATH:
break;
case _RPC_CIRCUIT_V:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
case _RPC_CIRCUIT_N:
if ((nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
continue;
break;
case _RPC_DATAGRAM_V:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
case _RPC_DATAGRAM_N:
if (nconf->nc_semantics != NC_TPI_CLTS)
continue;
break;
case _RPC_TCP:
if (((nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
(strcmp(nconf->nc_protofmly, NC_INET) &&
strcmp(nconf->nc_protofmly, NC_INET6)) ||
strcmp(nconf->nc_proto, NC_TCP))
continue;
break;
case _RPC_UDP:
if ((nconf->nc_semantics != NC_TPI_CLTS) ||
(strcmp(nconf->nc_protofmly, NC_INET) &&
strcmp(nconf->nc_protofmly, NC_INET6)) ||
strcmp(nconf->nc_proto, NC_UDP))
continue;
break;
case _RPC_LOCAL:
case _RPC_DOOR_LOCAL:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
if (strcmp(nconf->nc_protofmly, NC_LOOPBACK))
continue;
break;
}
break;
}
return (nconf);
}
void
__rpc_endconf(void *vhandle)
{
struct handle *handle;
handle = (struct handle *)vhandle;
if (handle == NULL)
return;
if (handle->nflag) {
(void) endnetpath(handle->nhandle);
} else {
(void) endnetconfig(handle->nhandle);
}
free(handle);
}
void *
rpc_nullproc(CLIENT *clnt)
{
struct timeval TIMEOUT = {25, 0};
if (clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_void, NULL, TIMEOUT) != RPC_SUCCESS)
return (NULL);
return ((void *)clnt);
}
struct netconfig *
__rpcfd_to_nconf(int fd, int servtype)
{
struct stat statbuf;
void *hndl;
struct netconfig *nconf, *newnconf = NULL;
major_t fdmajor;
struct t_info tinfo;
if (fstat(fd, &statbuf) == -1)
return (NULL);
fdmajor = major(statbuf.st_rdev);
if (servtype == 0) {
if (t_getinfo(fd, &tinfo) == -1) {
char errorstr[100];
__tli_sys_strerror(errorstr, sizeof (errorstr),
t_errno, errno);
(void) syslog(LOG_ERR, "__rpcfd_to_nconf : %s : %s",
"could not get transport information",
errorstr);
return (NULL);
}
servtype = tinfo.servtype;
}
hndl = setnetconfig();
if (hndl == NULL)
return (NULL);
while (nconf = getnetconfig(hndl)) {
if (__rpc_matchserv(servtype, nconf->nc_semantics) == TRUE) {
if (!stat(nconf->nc_device, &statbuf)) {
if (fdmajor == major(statbuf.st_rdev))
break;
if (fdmajor == minor(statbuf.st_rdev))
break;
}
}
}
if (nconf)
newnconf = getnetconfigent(nconf->nc_netid);
(void) endnetconfig(hndl);
return (newnconf);
}
int
__rpc_matchserv(int servtype, unsigned int nc_semantics)
{
switch (servtype) {
case T_COTS:
if (nc_semantics == NC_TPI_COTS)
return (TRUE);
break;
case T_COTS_ORD:
if (nc_semantics == NC_TPI_COTS_ORD)
return (TRUE);
break;
case T_CLTS:
if (nc_semantics == NC_TPI_CLTS)
return (TRUE);
break;
default:
break;
}
return (FALSE);
}
extern bool_t __inet_netdir_is_my_host(const char *);
bool_t
__rpc_is_local_host(const char *host)
{
char buf[MAXHOSTNAMELEN + 1];
if (host == NULL || strcmp(host, "localhost") == 0 ||
strcmp(host, HOST_SELF) == 0 ||
strcmp(host, HOST_SELF_CONNECT) == 0 ||
strlen(host) == 0)
return (TRUE);
if (sysinfo(SI_HOSTNAME, buf, sizeof (buf)) < 0)
return (FALSE);
if (strcmp(host, buf) == 0)
return (TRUE);
return (__inet_netdir_is_my_host(host));
}
bool_t
__rpc_try_doors(const char *nettype, bool_t *try_others)
{
switch (getnettype(nettype)) {
case _RPC_DOOR:
*try_others = FALSE;
return (TRUE);
case _RPC_DOOR_LOCAL:
case _RPC_DOOR_NETPATH:
*try_others = TRUE;
return (TRUE);
default:
*try_others = TRUE;
return (FALSE);
}
}