/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* 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) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*/
/*
* svc_dg.c, Server side for connectionless RPC.
*
* Does some caching in the hopes of achieving execute-at-most-once semantics.
*/
#include "mt.h"
#include "rpc_mt.h"
#include <stdio.h>
#include <sys/sysmacros.h>
#include <rpcsvc/svc_dg_priv.h>
#include <errno.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <ucred.h>
#include <unistd.h>
#ifdef RPC_CACHE_DEBUG
#include <netconfig.h>
#include <netdir.h>
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
static struct xp_ops *svc_dg_ops();
static void cache_set();
static int cache_get();
/*
* Usage:
* xprt = svc_dg_create(sock, sendsize, recvsize);
* Does other connectionless specific initializations.
* Once *xprt is initialized, it is registered.
* see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
* system defaults are chosen.
* The routines returns NULL if a problem occurred.
*/
static const char svc_dg_err3[] =
"fd > FD_SETSIZE; Use rpc_control(RPC_SVC_USE_POLLFD,...);";
/* Structure used to initialize SVC_XP_AUTH(xprt).svc_ah_ops. */
extern struct svc_auth_ops svc_auth_any_ops;
void
{
/* LINTED pointer alignment */
/* LINTED pointer alignment */
return;
}
if (rpc_buffer(xprt))
}
SVCXPRT *
{
if (RPC_FD_NOTIN_FDSET(fd)) {
return (NULL);
}
return (NULL);
}
/*
* Find the receive and the send size
*/
return (NULL);
}
goto freedata;
/* LINTED pointer alignment */
goto freedata;
goto freedata;
/* LINTED pointer alignment */
/* LINTED pointer alignment */
return (xprt);
if (xprt)
return (NULL);
}
SVCXPRT *
{
return (xprt);
}
SVCXPRT *
{
return (NULL);
/* LINTED pointer alignment */
/* LINTED pointer alignment */
return (NULL);
}
}
return (NULL);
}
}
return (NULL);
}
return (NULL);
}
/* LINTED pointer alignment */
return (NULL);
}
return (xprt);
}
/*ARGSUSED*/
static enum xprt_stat
{
return (XPRT_IDLE);
}
/*
* Find the SCM_UCRED in src and place a pointer to that option alone in dest.
* Note that these two 'netbuf' structures might be the same one, so the code
* has to be careful about referring to src after changing dest.
* Note that we cannot change the buf pointer otherwise maxlen will lose
* its meaning.
*/
static void
{
unsigned int olen;
/* LINTED: pointer alignment */
break;
return;
}
}
}
/*
* This routine extracts the destination IP address of the inbound RPC packet
* and sets that as source IP address for the outbound response.
*/
static void
{
/* extract dest IP of inbound packet */
/* LINTED pointer alignment */
return;
/* do nothing for non-IPv4 packet */
return;
/* set desired option header */
sizeof (struct T_opthdr) + sizeof (in_pktinfo_t));
return;
/*
* 1. set source IP of outbound packet
* 2. value '0' for index means IP layer uses this as source address
*/
pktinfo->ipi_ifindex = 0;
/* copy data into ancillary buffer */
}
}
static bool_t
{
/* LINTED pointer alignment */
int moreflag;
/* XXX: tudata should have been made a part of the server handle */
moreflag = 0;
#ifdef RPC_DEBUG
#endif
int lookres;
(struct t_uderr *)0) < 0)) {
/*EMPTY*/
#ifdef RPC_DEBUG
"svc_dg_recv: t_rcvuderr t_errno = %d\n",
t_errno);
#endif
}
goto again;
goto again;
else {
return (FALSE);
}
}
if ((moreflag) ||
/*
* If moreflag is set, drop that data packet. Something wrong
*/
return (FALSE);
}
XDR_SETPOS(xdrs, 0);
return (FALSE);
char *reply;
/* tu_data.addr is already set */
return (FALSE);
}
}
/*
* get local ip address
*/
/* LINTED pointer cast */
if (__rpc_get_ltaddr(nbufp,
NC_INET) == 0) {
"svc_dg_recv: ip(udp), "
"t_errno=%d, errno=%d",
}
NC_INET6) == 0) {
"svc_dg_recv: ip (udp6), "
"t_errno=%d, errno=%d",
}
return (FALSE);
}
}
}
}
return (TRUE);
}
static bool_t
{
/* LINTED pointer alignment */
} else
XDR_SETPOS(xdrs, 0);
/* LINTED pointer alignment */
xdr_location))) {
int slen;
}
} else {
goto try_again;
"svc_dg_reply: t_sndudata error t_errno=%d ",
}
}
return (stat);
}
static bool_t
{
if (svc_mt_mode != RPC_SVC_MT_NONE)
/* LINTED pointer alignment */
}
static bool_t
{
/* LINTED pointer alignment */
}
static void
{
(void) mutex_lock(&svc_mutex);
(void) mutex_unlock(&svc_mutex);
}
void
{
if (svc_mt_mode != RPC_SVC_MT_NONE) {
/* LINTED pointer alignment */
/* LINTED pointer alignment */
/* LINTED pointer alignment */
/* LINTED pointer alignment */
return;
}
if (svc_mt_mode != RPC_SVC_MT_NONE)
else
}
/*ARGSUSED*/
static bool_t
{
switch (rq) {
case SVCGET_XID:
return (FALSE);
/* LINTED pointer alignment */
return (TRUE);
default:
return (FALSE);
}
}
static struct xp_ops *
svc_dg_ops(void)
{
/* VARIABLES PROTECTED BY ops_lock: ops */
(void) mutex_lock(&ops_lock);
}
(void) mutex_unlock(&ops_lock);
return (&ops);
}
/* The CACHING COMPONENT */
/*
* Could have been a separate file, but some part of it depends upon the
* private structure of the client handle.
*
* Fifo cache for cl server
* Copies pointers to reply buffers into fifo cache
* Buffers are sent again if retransmissions are detected.
*/
/*
* An entry in the cache
*/
struct cache_node {
/*
* Index into cache is xid, proc, vers, prog and address
*/
/*
* The cached reply and length
*/
char *cache_reply;
/*
* Next node on the list, if there is a collision
*/
};
/*
* The entire cache
*/
struct cl_cache {
};
/*
* the hashing function
*/
extern mutex_t dupreq_lock;
/*
* Enable use of the cache. Returns 1 on success, 0 on failure.
* Note: there is no disable.
*/
int
{
/* LINTED pointer alignment */
/* LINTED pointer alignment */
else
/* LINTED pointer alignment */
(void) mutex_lock(&dupreq_lock);
enable_err, " ");
(void) mutex_unlock(&dupreq_lock);
return (0);
}
alloc_err, " ");
(void) mutex_unlock(&dupreq_lock);
return (0);
}
uc->uc_nextvictim = 0;
(void) mutex_unlock(&dupreq_lock);
return (0);
}
(void) mutex_unlock(&dupreq_lock);
return (0);
}
(void) mutex_unlock(&dupreq_lock);
return (1);
}
/*
* Set an entry in the cache. It assumes that the uc entry is set from
* the earlier call to cache_get() for the same procedure. This will always
* happen because cache_get() is calle by svc_dg_recv and cache_set() is called
* by svc_dg_reply(). All this hoopla because the right RPC parameters are
* not available at svc_dg_reply time.
*/
static void
{
int my_mallocs = 0;
#ifdef RPC_CACHE_DEBUG
char *uaddr;
#endif
/* LINTED pointer alignment */
/* LINTED pointer alignment */
else
/* LINTED pointer alignment */
/* LINTED pointer alignment */
(void) mutex_lock(&dupreq_lock);
/*
* Find space for the new entry, either by
* reusing an old entry, or by mallocing a new one
*/
/* LINTED pointer alignment */
;
(void) mutex_unlock(&dupreq_lock);
return;
}
} else {
(void) mutex_unlock(&dupreq_lock);
return;
}
(void) mutex_unlock(&dupreq_lock);
return;
}
my_mallocs = 1;
}
/*
* Store it away
*/
#ifdef RPC_CACHE_DEBUG
"cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
}
#endif
if (my_mallocs) {
}
(void) mutex_unlock(&dupreq_lock);
return;
}
/* LINTED pointer alignment */
(void) mutex_unlock(&dupreq_lock);
}
/*
* Try to get an entry from the cache
* return 1 if found, 0 if not found and set the stage for cache_set()
*/
static int
{
#ifdef RPC_CACHE_DEBUG
char *uaddr;
#endif
/* LINTED pointer alignment */
/* LINTED pointer alignment */
else
/* LINTED pointer alignment */
/* LINTED pointer alignment */
(void) mutex_lock(&dupreq_lock);
/* LINTED pointer alignment */
#ifdef RPC_CACHE_DEBUG
"cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
}
#endif
(void) mutex_unlock(&dupreq_lock);
return (1);
}
}
/*
* Failed to find entry
* Remember a few things so we can do a set later
*/
(void) mutex_unlock(&dupreq_lock);
return (0);
}