Intial commit

This commit is contained in:
Mario Fetka
2024-05-27 16:13:40 +02:00
parent f8dc12b10a
commit d71d446104
2495 changed files with 539746 additions and 0 deletions

1
prospero/lib/ardp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

32
prospero/lib/ardp/FILES Normal file
View File

@@ -0,0 +1,32 @@
FILES
Makefile
ardp.doc
ardp_abort.c
ardp_accept.c
ardp_add2req.c
ardp_breply.c
ardp_error.c
ardp_get_nxt.c
ardp_headers.c
ardp_int_err.c
ardp_mutexes.c
ardp_perrno.c
ardp_pr_actv.c
ardp_ptalloc.c
ardp_reply.c
ardp_respond.c
ardp_retriev.c
ardp_rqalloc.c
ardp_send.c
ardp_showbuf.c
ardp_snd_pkt.c
ardp_srv_ini.c
ardp_xmit.c
dnscache_alloc.c
dnscache_alloc.h
flocks.c
flocks.h
hostname2adr.c
p__th_self_num.c
unixerrstr.c
usc_lic_str.c

246
prospero/lib/ardp/Makefile.in Executable file
View File

@@ -0,0 +1,246 @@
#
# Makefile for Prospero Directory Service ARDP library.
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
CFLAGS += -I$(ARCHIE_ROOT)/include
CFILES = ardp_abort.c \
ardp_accept.c \
ardp_add2req.c \
ardp_breply.c \
ardp_error.c \
ardp_get_nxt.c \
ardp_headers.c \
ardp_int_err.c \
ardp_mutexes.c \
ardp_perrno.c \
ardp_pr_actv.c \
ardp_ptalloc.c \
ardp_reply.c \
ardp_respond.c \
ardp_retriev.c \
ardp_rqalloc.c \
ardp_send.c \
ardp_showbuf.c \
ardp_snd_pkt.c \
ardp_srv_ini.c \
ardp_xmit.c \
dnscache_alloc.c \
flocks.c \
hostname2adr.c \
p__th_self_num.c \
restrict.c \
unixerrstr.c \
usc_lic_str.c
OBJECTS = ardp_abort.o \
ardp_accept.o \
ardp_add2req.o \
ardp_breply.o \
ardp_error.o \
ardp_get_nxt.o \
ardp_headers.o \
ardp_int_err.o \
ardp_mutexes.o \
ardp_perrno.o \
ardp_pr_actv.o \
ardp_ptalloc.o \
ardp_reply.o \
ardp_respond.o \
ardp_retriev.o \
ardp_rqalloc.o \
ardp_send.o \
ardp_showbuf.o \
ardp_snd_pkt.o \
ardp_srv_ini.o \
ardp_xmit.o \
dnscache_alloc.o \
flocks.o \
hostname2adr.o \
p__th_self_num.o \
restrict.o \
unixerrstr.o \
usc_lic_str.o
all: ${RDP_LIB}
install:
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
${RDP_LIB}: ${OBJECTS}
rm -f ${RDP_LIB}
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
$(RANLIB) ${RDP_LIB}
# Dependencies
ardp_abort.o : ../../include/posix_signal.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/implicit_fixes.h \
../../include/ardp.h \
../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h
ardp_accept.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pserver.h ../../include/plog.h \
../../include/pprot.h
ardp_add2req.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_breply.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_error.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_get_nxt.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_headers.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_int_err.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_mutexes.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_perrno.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_pr_actv.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_ptalloc.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/mitra_macros.h
ardp_reply.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_respond.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h
ardp_retriev.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_rqalloc.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_send.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/pcompat.h
ardp_showbuf.o :
ardp_snd_pkt.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h \
../../include/perrno.h
ardp_srv_ini.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h
ardp_xmit.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
dnscache_alloc.o : dnscache_alloc.h ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/mitra_macros.h
flocks.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/plog.h \
flocks.h ../../include/mitra_macros.h
hostname2adr.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/string_with_strcasecmp.h \
../../include/pserver.h dnscache_alloc.h ../../include/pcompat.h \
../../include/mitra_macros.h
p__th_self_num.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
unixerrstr.o : ../../include/pmachine.h
usc_lic_str.o :

85
prospero/lib/ardp/Makefile.tmp Executable file
View File

@@ -0,0 +1,85 @@
#
# Makefile for Prospero Directory Service ARDP library.
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
CFILES = ardp_abort.c \
ardp_accept.c \
ardp_add2req.c \
ardp_breply.c \
ardp_error.c \
ardp_get_nxt.c \
ardp_headers.c \
ardp_int_err.c \
ardp_mutexes.c \
ardp_perrno.c \
ardp_pr_actv.c \
ardp_ptalloc.c \
ardp_reply.c \
ardp_respond.c \
ardp_retriev.c \
ardp_rqalloc.c \
ardp_send.c \
ardp_showbuf.c \
ardp_snd_pkt.c \
ardp_srv_ini.c \
ardp_xmit.c \
dnscache_alloc.c \
flocks.c \
hostname2adr.c \
p__th_self_num.c \
unixerrstr.c \
usc_lic_str.c
OBJECTS = ardp_abort.o \
ardp_accept.o \
ardp_add2req.o \
ardp_breply.o \
ardp_error.o \
ardp_get_nxt.o \
ardp_headers.o \
ardp_int_err.o \
ardp_mutexes.o \
ardp_perrno.o \
ardp_pr_actv.o \
ardp_ptalloc.o \
ardp_reply.o \
ardp_respond.o \
ardp_retriev.o \
ardp_rqalloc.o \
ardp_send.o \
ardp_showbuf.o \
ardp_snd_pkt.o \
ardp_srv_ini.o \
ardp_xmit.o \
dnscache_alloc.o \
flocks.o \
hostname2adr.o \
p__th_self_num.o \
unixerrstr.o \
usc_lic_str.o
all: ${RDP_LIB}
install:
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
${RDP_LIB}: ${OBJECTS}
rm -f ${RDP_LIB}
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
$(RANLIB) ${RDP_LIB}
# Dependencies
setdependencies:
gcc -M $(CFLAGS) $(CFILES) | sed \
-e 's, [^ ]*\.c,,' \
-e 's, /local/gnu/[^ ]*,,g' \
-e 's, /usr/include/[^ ]*,,g' \
-e 's, [./]*include/pthread\.h,,' \
-e 's, [./]*include/pthread/[^ ]*,,g' \
-e 's, [^ ]*/fsu_pthreads/include/[^ ]*,,g' \
-e 's, [./]*include/usc-copyr\.h,,' \
-e 's, [./]*include/usc-license\.h,,' \
-e 's, [./]*include/uw-copyright\.h,,' \
-e '/^[ ]*\\$$/d' | fixdep > dependency.list

262
prospero/lib/ardp/ardp.doc Normal file
View File

@@ -0,0 +1,262 @@
To use the library, include the file <ardp.h>.
The current release has dependencies upon Prospero in a few places:
If you will not be using the Prospero pauth structure, undefine
PROSPERO in ardp.h. The RREQ structure includes a reference to PAUTH
by default.
The ARDP library server routines currently call the Prospero function
plog(). A useful future direction is to make the logging function
application-specific, and inactive by default.
The ardp_reply_bst() function depends upon Propero bstrings. It will
not be included in the library if PROSPERO is not defined in ardp.h.
---
Error handling: ARDP library functions return error codes between 1
and 20. A return value of 0 is ARDP_SUCCESS. In addition, the global
variable
extern int perrno;
is generally set to the number of the error. (We haven't actually
checked every function in the ARDP library to guarantee this). This
global variable is used in the ARDP library, and in the PFS library.
The function p_clear_errors() should be called from your application
to clear this error indication. If you've linked with the PFS library
version, then p_clear_errors() will also clear Prospero error and
warning indications. This function is defined both in the PFS library
and in the ARDP library; if you're a PFS library and an ARDP library
user, place the PFS library version first in your link path. Its
declaration is:
extern void p_clear_errors(void);
Printed strings associated with these errors can be found in
lib/pfs/perrmesg.c. These are not currently available through the
ARDP library interface, although it does not depend upon them being
present. A future direction is to make these strings available
through the RDP library interface.
--
The ARDP library is now completely safe for sending arbitrary
length-coded binary data. (Until Prospero release Alpha.5.3, this was
not the case -- the server library used to append nulls to packets.)
--
Notes on the PTEXT structure:
The PTEXT structure has two members, ->text and ->start. On the user
side, they are currently always the same; however, this is not always
guaranteed to be the case in future releases of the ARDP library.
->text is used for the start of data to be parsed by the higher-level
application (e.g., Prospero). The ->length member of the PTEXT
structure is relative to ->start, which in this case is the same as
->text, but which is not guaranted to be so. Thus, if you need the
length of the text (relative to the start of ->text), it is ->length -
(->text - ->start).
--
Notes on the functions:
In the functions that follow, more details on the function can be
found in the header preceding the function in the source code. This
documentation is solely for the purpose of helping you decide which
functions to look at. (Another way of saying that we are well aware
that this manual is pretty sketchy.) Functions in the library that
are not described here should be considered internal and should not be
called by the application.
The following functions are exported by the ardp library for use by
the client side of a connection:
ardp_abort(req) Aborts the specified request, sending an
abort message to the server if currently
active. If req is null, will send aborts
to servers for all active requests.
ardp_abort_on_int() Sets interrupt handler to abort any
pending requests.
ardp_pr_active() Processes new responses to active requests.
If making an asynchronous request (i.e. ttwait
does not equal ARDP_WAIT_TILL_TO), then this
function must be called periodically, either
automatically within ardp_retrieve, explicitly,
or initiated by an interrupt when
a response becomes available on the UDP port.
ardp_retrieve(req,ttwait)
Poll for, or wait for a pending request to
complete.
ardp_send(req,dname,dest,ttwait)
Sends request to host with domain name
or socket address dest, and waits ttwait
microseconds for response (-1 means till timeout).
ardp_set_retry(to,rt) Set retry time out (seconds) and count
The following functions are exported by the ardp library for use by
the server side of a connection:
ardp_accept() Accepts new requests and places on appropriate
queues for subsequent processing. This must
be called periodically, either explicitly, or
initiated by an interrupt when a request
becomes available on the UDP port.
ardp_bind_port(portname)
Takes the name of (or #number) of a port to
be opened, on which the server will listen
for requests.
RREQ ardp_get_nxt() Returns the next request to be processed.
If none available, it will block until
one is received.
ardp_redirect(req,target)
Sends a redirect to the client indicating the
the request should be sent to a new target
server identified in the second argument.
ardp_respond(req,opt) Used by a server to send the current response
packet once filled in. It will add the packet
to the transmission queue, and send it. To
indicate completion of a response, the
ARDP_RESP_COMPLETE option should be specified.
If the ARDP_RESP_NOSEND option is specified,
the packet will be added to the transmission queue
but not sent.
ardp_refuse(req) Causes the specified request to be refused and
notification sent to the client.
ardp_reply(req,flags,message)
Queues message (appending it to the req structure)
and possibly sends it and other queued data to the
client. Will call ardp_respond() if any
completed packets can be sent (i.e., sends a
partial response to speed up client/server
interaction). Message is a null-terminated buffer.
Can't use this interface to send binary data
that might contain nulls; see
ardp_reply_bst() below.
ardp_rwait(req,timetowait,qpos,stime)
This function is called by a server to specify
a server requested time to wait for a response.
This value is returned to the client which
will treat it as an acknowledgment and will
defer subsequent timeouts and retries until
waiting the specified period. Non-zero values
for qpos and stime will cause the current
the specified queue position and expected
system time to be provided to the client in
the same message.
ardp_set_queuing_policy(pf,override)
Sets a function used to determine queue
ordering on the server.
ardp_set_prvport(fd) Sets a file descriptor that has already been
opened as the input port on which the server
will listen for requests.
The following functions are exported by the ardp library for use by
both the client and server sides of a connection:
ardp_add2req(req,flags,buf,len)
Adds text to a request which will subsequently
be sent to the peer, and returns.
RREQ ardp_rqalloc() Allocate a new request structure
ardp_rqfree(req) Free a request structure
ardp_rqlfree(req) Free a list of request structures
PTEXT ardp_ptalloc() Allocate a new packet structure
ardp_ptfree(pkt) Free a packet structure
ardp_ptlfree(pkt) Free a list of packet structures
/********************/
Internal functions:
ardp_showbuf() is used to display buffers that might contain
nulls.
/******************/
Eventually to be built on top of the above:
rd_sbuf Synchronously send a buffer to a destination
rd_sbufa Asynchronously send a buffer to a destination
rd_sync Wait until all pending requests are complete
/********************/
The ARDP library respects the global integer variable pfs_debug.
Levels of 9 or above cause the text of packets sent across the network
to be displayed to stderr.
As of Prospero Alpha.5.3 release, an ARDP library pfs_debug level of
11 or greater will cause \n and \t and \r to be printed as \n and \t
and \r in the display of the contents of ARDP packets. Levels 9 and
10 cause them to be displayed as themselves. All other control
characters in packets are now displayed as a \ followed by the
character's octal code. (In previous releases, they were displayed as
literal text, and nulls in the packet caused the display of the packet
text to be ignored.)
/*************/
The new ARDP_REPLY_BST() function accepts a Prospero BSTRING as its
argument. This violates modularity of the ARDP library, since it
requires the ARDP library to know about the bstrings layer. We need a
new interface to ardp_reply() that will accept a length-coded buffer,
and then a wrapper around it in the pfs library that will accept the
bstring. Future directions for this function are noted at ISI in
/nfs/pfs/notes/ardp-directions.
ardp_reply_bst(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message) /* The data to be sent. Must be a bstring. */
/**** BUGS & future directions *****/
ardp_retrieve() and ardp_send() both call p_clear_errors() internally.
This is inconsistent with the behavior of the rest of the ARDP library
and of most of the PFs library, which do not clear error indications
themselves.
Look over ardp.h.
-Make it independent of Prospero directory service: Put authentication
stuff into ardp.h as a formal library. Alternatively, make the
directory service use the 'app' optional member. (at least until the
authentication stuff is better defined).
Make sure the app optional member is defined and explained in the ARDP stuff.
-Get rid of #define PROSPERO in ardp.h
-ARDP_DEFAULT_PEER and ARDP_DEFAULT_PORT must become optional
constants.
Change the ardp library interface so that the logging function is
specified at runtime initialization.
ardp_reply should have the interface changed to accept a message
length, just like ardp_add2req() does. Ditto any other functions in the
libardp interface that expect just null terminated buffers. The ARDP
library should be better documented for potential programmers.
Fix bug: ardp_respond() expects trailing null on buffer
ardp_add2req() hands. (this is on the SWA todo list as a separate
item).
SWA has rewritten ardp_add2req on paper; need to type in these
simplifying changes.

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to abort pending requests
*/
#include <usc-copyr.h>
#include <posix_signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pfs_threads.h>
#include <list_macros.h>
#include <implicit_fixes.h>
#include <ardp.h>
#include <pmachine.h>
extern RREQ ardp_activeQ; /* Info about active requests */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
extern int ardp_activeQ_len; /* Length of ardp_activeQ */
/*
* ardp_abort - abort a pending request
*
* ardp_abort takes a pointer to a request structure of a request to
* be aborted, sends an abort request to the server handling the pending,
* request, and immediately returns. If the request is null (NOREQ), then
* all requests on the ardp_activeQ are aborted.
*/
int
ardp_abort(req)
RREQ req; /* Request to be aborted */
{
PTEXT ptmp = NOPKT; /* Abort packet to be sent */
RREQ rtmp = NOREQ; /* Current request to abort */
int ns; /* Number of bytes actually sent */
if(req && (req->status != ARDP_STATUS_ACTIVE)) return(ARDP_BAD_REQ);
if(req) rtmp = req;
else rtmp = ardp_activeQ;
ptmp = ardp_ptalloc();
/* Add header */
ptmp->start -= 13;
ptmp->length += 13;
*(ptmp->start) = (char) 13;
/* An unsequenced control packet */
bzero(ptmp->start+3,10);
/* Cancel flag */
*(ptmp->start+12) = 0x01;
while(rtmp) {
bcopy2(&(rtmp->cid),ptmp->start+1);
if (pfs_debug >= 6) {
if(rtmp->peer.sin_family == AF_INET)
fprintf(stderr,"\nSending abort message (cid=%d) to %s(%d)...",
ntohs(rtmp->cid),inet_ntoa(rtmp->peer_addr),PEER_PORT(rtmp));
else fprintf(stderr,"\nSending abort message...");
(void) fflush(stderr);
}
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
&(rtmp->peer), S_AD_SZ);
if(ns != ptmp->length) {
if (pfs_debug) {
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
perror("");
}
ardp_ptfree(ptmp);
return(ARDP_NOT_SENT);
}
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
rtmp->status = ARDP_STATUS_ABORTED;
EXTRACT_ITEM(rtmp,ardp_activeQ);
--ardp_activeQ_len;
if(req) rtmp = NOREQ;
else rtmp = rtmp->next;
}
ardp_ptfree(ptmp);
return(ARDP_SUCCESS);
}
/*
* ardp_trap_int - signal handler to abort request on ^C
*/
SIGNAL_RET_TYPE ardp_trap_int()
{
ardp_abort(NOREQ);
exit(1);
}
/*
* ardp_abort_on_int - set up signal handler to abort request on ^C
*/
int
ardp_abort_on_int()
{
signal(SIGINT,ardp_trap_int);
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,752 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as check_for_messages in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
* Modified by swa 12/93 made handle arbitrary length ardp_runQ
* Modified by swa 3/95 for bunyip; trapping errno 9 in bad rcvfrom.
*/
/* This version of lib/ardp/ardp_accept.c will work both in Prospero
Prealpha.17May94 and in the current (as of 3/21/95) working sources at ISI.
*/
#include <usc-license.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/param.h>
/* Need types.h for u_short */
#include <sys/types.h>
#include <sys/socket.h>
#ifdef AIX
#include <sys/select.h>
#endif
#ifdef SOLARIS
#include <sys/signal.h>
#endif
#include <errno.h>
#include <ardp.h>
#include <pserver.h>
#include <plog.h>
#include <pprot.h>
#include <pmachine.h>
#include <pfs_threads.h> /* Mutex stuff */
#define LOG_PACKET(REQ,QP) \
if((REQ)->priority || (pQlen > 4)) \
if(pQNlen && (REQ)->priority) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d) - Priority %d", \
QP, pQlen, pQNlen, (REQ)->priority, 0); \
else if(pQNlen) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d)", \
QP, pQlen, pQNlen, 0); \
else if((REQ)->priority) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d - Priority %d", \
QP, pQlen, (REQ)->priority, 0); \
else if(QP != pQlen) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d", QP, pQlen, 0); \
else plog(L_QUEUE_INFO, REQ, "Queued: %d", pQlen, 0);
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_pendingQ,NOREQ); /*Pending requests*/
int pQlen = 0; /* Length of pending queue */
int pQNlen = 0; /* Number of niced requests */
static RREQ ardp_partialQ = NOREQ; /* Incomplete requests */
int ptQlen = 0; /* Length of incomplete queue */
int ptQmaxlen = 20; /* Max length of incomplete queue */
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_runQ,NOREQ); /* Requests currently in
progress */
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_doneQ,NOREQ); /* Processed requests
*/
int dQlen = 0; /* Length of reply queue */
/* Mutexed with ardp_doneQ */
int dQmaxlen = 20; /* Max length of reply queue */
static struct timeval zerotime = {0, 0}; /* Used by select */
#define max(x,y) (x > y ? x : y)
extern int (*ardp_pri_func)(); /* Function to compare priorities */
extern int ardp_pri_override; /* If 1, overide value in request */
/* C library error facility */
extern int ardp_srvport;
extern int ardp_prvport;
#ifdef ARCHIE
#ifdef __STDC__
extern int arch_get_etime(RREQ);
#else
extern int arch_get_etime();
#endif
#endif
static void ardp_update_cfields(RREQ existing, RREQ newvalues);
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
int is_rwait_needed);
int
ardp_accept_and_wait(int timeout, int usec)
{
struct sockaddr_in from;
int fromlen;
int n = 0;
PTEXT pkt;
unsigned char flags1,flags2;
unsigned short pid; /* protocol ID for higher-level protocol */
int qpos; /* Position of new req in queue */
int dpos; /* Position of dupe in queue */
RREQ creq; /* Current request */
RREQ treq; /* Temporary request pointer */
RREQ nreq; /* New request pointer */
RREQ areq = NOREQ; /* Request needing ack */
RREQ match_in_runQ = NOREQ; /* if match found in runq for
completed request. */
int hdr_len;
char *ctlptr;
short stmp;
int tmp;
int check_for_ack = 1;
fd_set readfds; /* Used for select */
long now; /* Time - used for retries */
long rr_time = 0; /* Time last retrans from done queue */
struct timeval time_out;
time_out.tv_sec = timeout;
time_out.tv_usec = usec;
#ifdef PFS_THREADS
/* Changed from original interface. This will try the lock and return
an error if unsuccessful. Otherwise it will get the lock */
if (p_th_mutex_trylock(p_th_mutexARDP_ACCEPT))
return ARDP_SUCCESS; /* Being retrieved */
#endif
check_for_more:
/* This is initialized afresh before each select(). Some operating
systems, such as LINUX, modify the time_out parameter to SELECT().
--swa, 6/19/94 */
time_out.tv_sec = timeout;
time_out.tv_usec = usec;
now = time(NULL);
/* Check both the prived and unprived ports if necessary */
FD_ZERO(&readfds);
FD_SET(ardp_srvport, &readfds);
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
tmp = select(max(ardp_srvport,ardp_prvport) + 1,
&readfds,(fd_set *)0,(fd_set *)0,&time_out);
if(tmp == 0) {
if(areq) ardp_acknowledge(areq); areq = NOREQ;
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_SUCCESS;
}
if(tmp < 0) {
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_SELECT_FAILED;
}
creq = ardp_rqalloc();
pkt = ardp_ptalloc();
/* There is a message waiting, add it to the queue */
fromlen = sizeof(from);
if((ardp_prvport >= 0) && FD_ISSET(ardp_prvport,&readfds))
n = recvfrom(ardp_prvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
(struct sockaddr *) &from, &fromlen);
else {
assert(FD_ISSET(ardp_srvport, &readfds));
n = recvfrom(ardp_srvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
(struct sockaddr *) &from, &fromlen);
}
if (n <= 0) {
plog(L_NET_ERR,NOREQ,"Bad recvfrom n = %d errno = %d %s",
n, errno, unixerrstr(), 0);
/* I added this in response to a problem experienced by Bunyip.
--swa, 3/21/95 */
if (errno == 9) {
if ((ardp_prvport >= 0) && FD_ISSET(ardp_prvport, &readfds))
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
represented internally by the variable ardp_prvport", ardp_prvport);
else if (FD_ISSET(ardp_srvport, &readfds))
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
represented internally by the variable ardp_srvport", ardp_srvport);
else
internal_error("Something is wrong with your system's version
of select(). No descriptors are readable; unclear how we got here.");
plog(L_NET_ERR, NOREQ,
"This should never happen. Attempting to restart server with SIGUSR1.");
kill(getpid(), SIGUSR1); /* sending restart signal to Prospero
server or to whatever we hand*/
}
ardp_rqfree(creq); ardp_ptfree(pkt);
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_BAD_RECV;
}
bcopy(&from,&(creq->peer),sizeof(creq->peer));
creq->cid = 0; creq->peer_ardp_version = 0;
creq->rcvd_time.tv_sec = now;
creq->prcvd_thru = 0;
if ( ! verify_acl_list(&from) ) {
ardp_breply(creq, ARDP_R_COMPLETE, acl_message(),0);
ardp_ptfree(pkt);
goto check_for_more;
}
pkt->start = pkt->dat;
pkt->length = n;
*(pkt->start + pkt->length) = '\0';
pkt->mbz = 0; /* force zeros to catch runaway strings */
pkt->seq = 1;
if((hdr_len = (unsigned char) *(pkt->start)) < 32) {
ctlptr = pkt->start + 1;
pkt->seq = 0;
if(hdr_len >= 3) { /* Connection ID */
bcopy2(ctlptr,&stmp);
if(stmp) creq->cid = ntohs(stmp);
ctlptr += 2;
}
if(hdr_len >= 5) { /* Packet number */
bcopy2(ctlptr,&stmp);
pkt->seq = ntohs(stmp);
}
else { /* No packet number specified, so this is the only one */
pkt->seq = 1;
creq->rcvd_tot = 1;
}
ctlptr += 2;
if(hdr_len >= 7) { /* Total number of packets */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) creq->rcvd_tot = ntohs(stmp);
}
ctlptr += 2;
if(hdr_len >= 9) { /* Receievd through */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) {
creq->prcvd_thru = ntohs(stmp);
}
}
ctlptr += 2;
if(hdr_len >= 11) { /* Backoff */
/* Not supported by server */
}
ctlptr += 2;
flags1 = flags2 = 0;
if(hdr_len >= 12) flags1 = *ctlptr++; /* Flags */
if(hdr_len >= 13) flags2 = *ctlptr++; /* Flags */
if(flags2 == 1) { /* Cancel request */
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
treq = ardp_pendingQ;
while(treq) {
if((treq->cid == creq->cid) &&
(treq->peer_port == creq->peer_port) &&
(treq->peer_addr.s_addr == creq->peer_addr.s_addr)){
plog(L_QUEUE_INFO,treq,
"Request canceled by client - dequeued",0);
pQlen--;if(treq->priority > 0) pQNlen--;
EXTRACT_ITEM(treq,ardp_pendingQ);
ardp_rqfree(treq);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
goto check_for_more;
}
treq = treq->next;
}
plog(L_QUEUE_INFO,creq,
"Request canceled by client - not on queue",0);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
goto check_for_more;
}
/* If the client specifies option flags and doesn't specify control
info to match them, we probably should log this; right now we just
silently ignore it. */
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Priority specified. */
if(flags1 & 0x2) {
bcopy2(ctlptr,&stmp);
creq->priority = ntohs(stmp);
ctlptr += 2;
}
}
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Higher-level protocol ID follows. */
/* N.B.: used to be a bug here where this was 0x1; this is in
variance with the ARDP spec and I've corrected the
implementation to conform to the spec. */
if(flags1 & 0x4) {
bcopy2(ctlptr,&stmp);
pid = ntohs(stmp);
ctlptr += 2;
}
}
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Window size follows (2 octets of information). */
if(flags1 & 0x8) {
bcopy2(ctlptr,&stmp);
creq->pwindow_sz = ntohs(stmp);
ctlptr += 2;
if (creq->pwindow_sz == 0) {
creq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ;
plog(L_NET_INFO, creq,
"Client explicity reset window size to server \
default (%d)",
ARDP_DEFAULT_WINDOW_SZ);
} else {
if (creq->pwindow_sz > ARDP_MAX_WINDOW_SZ) {
plog(L_NET_INFO, creq, "Client set window size \
to %d; server will limit it to %d", creq->pwindow_sz, ARDP_MAX_WINDOW_SZ);
creq->pwindow_sz = ARDP_MAX_WINDOW_SZ;
} else {
plog(L_NET_INFO, creq,
"Client set window size to %d", creq->pwindow_sz);
}
}
}
}
if((creq->priority < 0) && (creq->priority != -42)) {
plog(L_NET_RDPERR, creq, "Priority %d requested - ignored", creq->priority, 0);
creq->priority = 0;
}
if(pkt->seq == 1) creq->rcvd_thru = max(creq->rcvd_thru, 1);
pkt->length -= hdr_len;
pkt->start += hdr_len;
pkt->text = pkt->start;
}
else {
/* When we are no longer getting any of these old format */
/* requests, we know that everyone is using the new */
/* reliable datagram protocol, and that they also */
/* have the singleton response bug fixed. We can then */
/* get rid of the special casing for singleton responses */
/* Lower the priority to encourage people to upgrade */
creq->priority = 1;
creq->peer_ardp_version = -1;
#ifdef LOGOLDFORMAT
plog(L_DIR_PWARN,creq,"Old RDP format",0);
#endif LOGOLDFORMAT
pkt->seq = 1;
creq->rcvd_tot = 1;
creq->rcvd_thru = 1;
}
/* Check to see if it is already on done, partial, or pending */
/* Done queue */
EXTERN_MUTEXED_LOCK(ardp_doneQ);
treq = ardp_doneQ;
CHECK_HEAD(treq);
while(treq) {
if((treq->cid != 0) && (treq->cid == creq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &from,sizeof(from))==0)){
/* Request is already on doneQ */
if(creq->prcvd_thru > treq->prcvd_thru) {
treq->prcvd_thru = creq->prcvd_thru;
rr_time = 0; /* made progress, don't supress retransmission */
}
nreq = treq;
/* Retransmit reply if not completely received */
/* and if we didn't retransmit it this second */
if((nreq->prcvd_thru != nreq->trns_tot) &&
((rr_time != now) || (nreq != ardp_doneQ))) {
PTEXT tpkt; /* Temporary pkt pointer */
plog(L_QUEUE_INFO,nreq,"Retransmitting reply (%d of %d ack)",
nreq->prcvd_thru, nreq->trns_tot, 0);
/* Transmit all outstanding packets */
for (tpkt = nreq->trns; tpkt; tpkt = tpkt->next) {
if((tpkt->seq <= (nreq->prcvd_thru + nreq->pwindow_sz)) &&
((tpkt->seq == 0) || (tpkt->seq > nreq->prcvd_thru))) {
/* (A) Request an ack at the end of a window
(B) Request an ack in the last packet if the
service has rescinded a wait request, but we
aren't sure that the client knows this.
*/
ardp_header_ack_rwait(tpkt, nreq,
/* do set ACK BIT: */
(/*A*/ tpkt->seq ==
(nreq->prcvd_thru
+ nreq->pwindow_sz))
|| /*B*/
((tpkt->seq == nreq->trns_tot)
/* last pkt */
&& (nreq->svc_rwait_seq >
nreq->prcvd_thru)),
/* Might an RWAIT be needed? */
(nreq->svc_rwait_seq >
nreq->prcvd_thru));
ardp_snd_pkt(tpkt,nreq);
}
}
rr_time = now; /* Remember time of retransmission */
}
/* Move matched request to front of queue */
/* nreq is definitely in ardp_doneQ right now. */
/* This replaces much icky special-case code that used to be here
-- swa, Feb 9, 1994 */
EXTRACT_ITEM(nreq, ardp_doneQ);
PREPEND_ITEM(nreq, ardp_doneQ);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
goto check_for_more;
}
/* While we're checking the done queue also see if any */
/* replies require follow up requests for acknowledgments */
/* This is currently used when the server has requested that the client
wait for a long time, and then has rescinded that wait request
(because the message is done). Such a rescinding of the wait
request should be received by the client, and the server is
expecting an ACK. */
/* You can add additional tests here if there are other circumstances
under which you want the server to expect the client to send an
acknowledgement. */
if(check_for_ack && (treq->svc_rwait_seq > treq->prcvd_thru) &&
(treq->retries_rem > 0) && (now >= treq->wait_till.tv_sec)) {
#define ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
#ifdef ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
plog(L_QUEUE_INFO,treq,"Requested ack not received - pinging client (%d of %d/%d ack)",
treq->prcvd_thru, treq->svc_rwait_seq, treq->trns_tot, 0);
#endif /* ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS */
/* Resend the final packet only - to wake the client */
if(treq->trns) ardp_snd_pkt(treq->trns->previous,treq);
treq->timeout_adj.tv_sec = ARDP_BACKOFF(treq->timeout_adj.tv_sec);
treq->wait_till.tv_sec = now + treq->timeout_adj.tv_sec;
treq->retries_rem--;
}
CHECK_NEXT(treq);
treq = treq->next;
} /*while*/
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
check_for_ack = 0; /* Only check once per call to ardp_accept */
/* If unsequenced control packet free it and check for more */
if(pkt->seq == 0) {
ardp_rqfree(creq); ardp_ptfree(pkt);
goto check_for_more;
}
/* Check if incomplete and match up with other incomplete requests */
if(creq->rcvd_tot != 1) { /* Look for rest of request */
treq = ardp_partialQ;
while(treq) {
if((treq->cid != 0) && (treq->cid == creq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &from,sizeof(from))==0)) {
/* We found the rest of the request */
/* coallesce and log and check_for more */
PTEXT tpkt; /* Temporary pkt pointer */
ardp_update_cfields(treq,creq);
if(creq->rcvd_tot) treq->rcvd_tot = creq->rcvd_tot;
tpkt = treq->rcvd;
while(tpkt) {
if(tpkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
if(tpkt->seq == pkt->seq) {
/* Duplicate - discard */
plog(L_NET_INFO,creq,"Multi-packet duplicate received (pkt %d of %d)",
pkt->seq, creq->rcvd_tot, 0);
if(areq != treq) {
if(areq) {
ardp_acknowledge(areq);
}
areq = treq;
}
ardp_rqfree(creq); ardp_ptfree(pkt);
goto check_for_more;
}
if(tpkt->seq > pkt->seq) {
/* Insert new packet in rcvd */
pkt->next = tpkt;
pkt->previous = tpkt->previous;
if(treq->rcvd == tpkt) treq->rcvd = pkt;
else tpkt->previous->next = pkt;
tpkt->previous = pkt;
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
while(tpkt && (tpkt->seq == treq->rcvd_thru+1)) {
treq->rcvd_thru++;
tpkt = tpkt->next;
}
pkt = NOPKT;
break;
}
tpkt = tpkt->next;
}
if(pkt) { /* Append at end of rcvd */
APPEND_ITEM(pkt,treq->rcvd);
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
pkt = NOPKT;
}
if(treq->rcvd_tot && (treq->rcvd_thru == treq->rcvd_tot)) {
if(areq == treq) areq = NOREQ;
creq = treq; EXTRACT_ITEM(creq, ardp_partialQ); --ptQlen;
plog(L_NET_INFO,creq,"Multi-packet request complete",0);
goto req_complete;
}
else {
if(areq != treq) {
if(areq) {
ardp_acknowledge(areq);
}
areq = treq;
}
plog(L_NET_INFO, creq,
"Multi-packet request continued (rcvd %d of %d)",
creq->rcvd_thru, creq->rcvd_tot, 0);
goto check_for_more;
}
}
treq = treq->next;
}
/* This is the first packet we received in the request */
/* log it and queue it and check for more */
plog(L_NET_INFO,creq,"Multi-packet request received (pkt %d of %d)",
pkt->seq, creq->rcvd_tot, 0);
APPEND_ITEM(pkt,creq->rcvd);
APPEND_ITEM(creq,ardp_partialQ); /* Add at end of incomp queue */
if(++ptQlen > ptQmaxlen) {
treq = ardp_partialQ; /* Remove from head of queue */
EXTRACT_ITEM(ardp_partialQ,ardp_partialQ); ptQlen--;
plog(L_NET_ERR, treq,
"Too many incomplete requests - dropped (rthru %d of %d)",
treq->rcvd_thru, treq->rcvd_tot, 0);
ardp_rqfree(treq);
}
goto check_for_more;
}
plog(L_NET_INFO, creq, "Received packet", 0);
req_complete:
qpos = 0; dpos = 1;
/* Insert this message at end of pending but make sure the */
/* request is not already in pending */
nreq = creq; creq = NOREQ;
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
treq = ardp_pendingQ;
if(pkt) {
nreq->rcvd_tot = 1;
APPEND_ITEM(pkt,nreq->rcvd);
}
EXTERN_MUTEXED_LOCK(ardp_runQ);
for (match_in_runQ = ardp_runQ; match_in_runQ;
match_in_runQ = match_in_runQ->next) {
if((match_in_runQ->cid == nreq->cid) && (match_in_runQ->cid != 0) &&
(bcmp((char *) &(match_in_runQ->peer),
(char *) &(nreq->peer),sizeof(nreq->peer))==0)) {
/* Request is running right now */
ardp_update_cfields(match_in_runQ,nreq);
plog(L_QUEUE_INFO,match_in_runQ,"Duplicate discarded (presently executing)",0);
/*!! This looks strange - freeing but not removing from ardp_runQ*/
ardp_rqfree(nreq);
nreq = match_in_runQ;
break; /* leave match_in_runQ set to nreq */
}
}
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
if (match_in_runQ) {
/* do nothing; handled above. */
} else if(ardp_pendingQ) {
int keep_looking = 1; /* Keep looking for dup. Initially say to
keep on looking. */
while(treq) {
if((treq->cid != 0) && (treq->cid == nreq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &(nreq->peer),sizeof(treq->peer))==0)){
/* Request is already on queue */
ardp_update_cfields(treq,nreq);
plog(L_QUEUE_INFO,treq,"Duplicate discarded (%d of %d)",dpos,pQlen,0);
ardp_rqfree(nreq);
nreq = treq;
keep_looking = 0; /* We found the duplicate */
break;
}
if((ardp_pri_override && ardp_pri_func && (ardp_pri_func(nreq,treq) < 0)) ||
(!ardp_pri_override && ((nreq->priority < treq->priority) ||
((treq->priority == nreq->priority) && ardp_pri_func &&
(ardp_pri_func(nreq,treq) < 0))))) {
if(ardp_pendingQ == treq) {
nreq->previous = ardp_pendingQ->previous;
nreq->next = ardp_pendingQ;
ardp_pendingQ->previous = nreq;
ardp_pendingQ = nreq;
}
else {
nreq->next = treq;
nreq->previous = treq->previous;
nreq->previous->next = nreq;
treq->previous = nreq;
}
pQlen++;
if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq, dpos);
qpos = dpos;
keep_looking = 1; /* There may still be a duplicate */
break;
}
if(!treq->next) {
treq->next = nreq;
nreq->previous = treq;
ardp_pendingQ->previous = nreq;
pQlen++;
if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq,dpos+1);
qpos = dpos+1;
keep_looking = 0; /* Nothing more to check */
break;
}
treq = treq->next;
dpos++;
}
/* Save queue position to send to client if appropriate */
qpos = dpos;
/* If not added at end of queue, check behind packet for dup */
if(keep_looking) {
while(treq) {
if((treq->cid == nreq->cid) && (treq->cid != 0) &&
(bcmp((char *) &(treq->peer),
(char *) &(nreq->peer),
sizeof(treq->peer))==0)){
/* Found a dup */
plog(L_QUEUE_INFO,treq,"Duplicate replaced (removed at %d)", dpos, 0);
pQlen--;if(treq->priority > 0) pQNlen--;
EXTRACT_ITEM(treq,ardp_pendingQ);
ardp_rqfree(treq);
break;
}
treq = treq->next;
dpos++;
}
} /* if keep_looking */
}
else {
nreq->next = NULL;
ardp_pendingQ = nreq;
ardp_pendingQ->previous = nreq;
pQlen++;if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq, dpos);
qpos = dpos;
}
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
/* Fill in queue position and system time */
nreq->inf_queue_pos = qpos;
/* nreq->inf_sys_time = **compute-system-time-here** */
#ifdef ARCHIE
nreq -> inf_sys_time = arch_get_etime(nreq);
#endif
/* Here we can optionally send a message telling the */
/* client to back off. How long should depend on the */
/* queue length and the mean service time */
/* 15 min for now - the archie server is overloaded */
#ifdef ARCHIE
/* This is an old version of the Prospero clients that only archie servers
will need to be able to talk to, so don't bother doing this test
for anything but an archie server. */
if((nreq->peer_ardp_version >= 0) && (sindex(nreq->rcvd->start,"VERSION 1")))
nreq->peer_ardp_version = -2;
/* Archie servers should request a longer wait. Other heavily used
databases may want to have this command defined too. */
ardp_rwait(nreq,900,nreq->inf_queue_pos,nreq->inf_sys_time);
#endif
goto check_for_more;
}
static
void
ardp_update_cfields(RREQ existing,RREQ newvalues)
{
if(newvalues->prcvd_thru > existing->prcvd_thru)
existing->prcvd_thru = newvalues->prcvd_thru;
}
/* Rewrite the header of TPKT to conform to the status in nreq. The only
fields
we need to set are possibly the ACK bit in octet 11 and possibly the rwait
field in octets 9 & 10. We always send the received-through field for the
sake of simplicity of implementation. */
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
int is_rwait_needed)
{
int new_hlength; /* new header length. */
int old_hlength; /* old header length */
unsigned short us_tmp; /* tmp for values. */
old_hlength = tpkt->text - tpkt->start;
/* If rwait needed, leave room for it. */
new_hlength = 9; /* Include room for received-through count */
if (is_rwait_needed)
new_hlength = 11;
if (is_ack_needed) new_hlength = 12;
/* Allocate space for new header. */
tpkt->start = tpkt->text - new_hlength;
tpkt->length += new_hlength - old_hlength;
/* Set the header length and version # (zeroth octet) */
/* Version # is zero in this version of the ARDP library; last 6 bytes
of octet are header length. */
*(tpkt->start) = (char) new_hlength;
/* Set octets 1 through 8 of header */
/* Connection ID (octets 1 & 2) */
bcopy2(&(nreq->cid),tpkt->start+1);
/* Sequence number (octets 3 & 4) */
us_tmp = htons(tpkt->seq);
bcopy2(&us_tmp,tpkt->start+3);
/* Total packet count (octets 5 & 6) */
us_tmp = htons(nreq->trns_tot);
bcopy2(&us_tmp,tpkt->start+5);
/* Received through (octets 7 & 8) */
us_tmp = htons(nreq->rcvd_thru);
bcopy2(&us_tmp,tpkt->start+7);
/* Now set any options. */
/* expected time 'till response */
if (new_hlength > 9) {
us_tmp = htons(nreq->svc_rwait);
bcopy2(&us_tmp, tpkt->start+9);
}
if (new_hlength > 11) {
tpkt->start[11] =
is_ack_needed ? 0x80 /* ACK BIT */ : 0x00 /* Don't ack */;
}
}
int
ardp_accept() {
return ardp_accept_and_wait(0,0);
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 2/93 to add text to a request
*/
#include <usc-copyr.h>
#include <string.h>
#include <stdio.h>
#include <ardp.h>
#include <sys/types.h> /* so pmachine.h won't redefine it. */
#include <pmachine.h> /* for bcopy() */
#define max(x,y) (x > y ? x : y)
#define min(x,y) (x < y ? x : y)
/*
* ardp_add2req - add text to request structure
*
* ardp_add2req takes a request structure, flags, a buffer containing text
* to be added to the output queue of the request, and the length of the
* buffer.
*
* If the specified length of the buffer is 0, ardp_add2req calculates
* it using strlen (if the lenght is zero, the assumption is that the
* buffer is null terminated).
* If the buffer is a NULL pointer and the specified length is 0, then
* it treated as a true zero-length buffer.
*
* If the flag ARDP_A2R_NOSPLITB is set, the request will not be split
* across packets. If ARDP_A2R_NOSPLITL, the lines may not be split
* across packets, and text added to a request without a trailing new
* line will be deferred until a newline is added or ardp_add2req is called
* without ARDP_A2R_NOSPLITL set. If ARDP_A2R_COMPLETE is specified, it
* indicates this is the final text to be added to the request structure,
* and no text will remain buffered. If there is still deferred text,
* a newline will be added. If the flag ARDP_A2R_TAGLENGTH is specified,
* the data written to the request will be tagged with a four octet length
* field in network byte order.
*
* NOTE: If you use this function to add text to a request, then you
* should use only this function. If this function is called on
* a request previously constructed by hand, unexpected failures
* may result.
*
* BUGS: ARDP_A2R_NOSPLITL is not currently supported unless
* ARDP_A2R_NOSPLITB is also set.
* ARDP_A2R_TAGLENGTH is not presently supported.
* An ardp_flush_partial_line() is needed to handle some manifestations
* of the ARDP_TOOLONG error. Alternatively, we might specify an
* additional flag to ardp_add2req() to specify the behavior on an
* ARDP_TOOLONG error.
*/
int
ardp_add2req(RREQ req, /* Request to get the text */
int flags, /* Options to add2req */
char *buf, /* New text for request */
int buflen) /* Length of the new text */
{
int remaining; /* Space remaining in pkt */
int written; /* # Octets written */
char *newline; /* last nl in string */
int deflen; /* Length of deferred text */
int extra; /* Extra space needed */
long taglen; /* Length in net byte ord */
PTEXT pkt = NOPKT; /* Current packet */
PTEXT ppkt; /* Previous packet */
/* Note: New text gets written after pkt->ioptr. If */
/* there is text waiting for a newline, then ->ioptr */
/* may be beyond ->start+->length, which will be the */
/* text up to the final newline seen so far */
/* XXX For now if NOSPLITL, must also specify NOSPLITB */
if((flags & ARDP_A2R_NOSPLITL) && !(flags & ARDP_A2R_NOSPLITB))
return(ARDP_FAILURE);
if(buf && !buflen) buflen = strlen(buf);
if(!buf) buf = "";
keep_writing:
/* Find ot allocate last packet in ->outpkt */
if(req->outpkt) pkt = req->outpkt->previous;
if(!pkt) {
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
APPEND_ITEM(pkt,req->outpkt);
}
deflen = pkt->ioptr - (pkt->start + pkt->length);
extra = deflen;
if(flags & ARDP_A2R_NOSPLITL) extra += 1;
if(flags & ARDP_A2R_TAGLENGTH) extra += 4;
if((flags & ARDP_A2R_NOSPLITB) && (buflen + extra > ARDP_PTXT_LEN))
return(ARDP_TOOLONG);
remaining = ARDP_PTXT_LEN - (pkt->ioptr - pkt->start);
if(((flags & ARDP_A2R_NOSPLITB) && (remaining < buflen + 1)) ||
((flags & ARDP_A2R_TAGLENGTH) && (remaining < 4)) ||
(remaining == 0)) {
ppkt = pkt;
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
if(ppkt->start + ppkt->length != ppkt->ioptr) {
/* Must move deferred text to new packet */
bcopy(ppkt->start+ppkt->length, pkt->start, deflen);
ppkt->ioptr = ppkt->start + ppkt->length;
*(ppkt->ioptr) = '\0';
pkt->ioptr += deflen;
}
APPEND_ITEM(pkt,req->outpkt);
remaining = ARDP_PTXT_LEN;
}
if(flags & ARDP_A2R_TAGLENGTH) {
taglen = htonl(buflen);
bcopy4(&buflen,pkt->ioptr);
pkt->ioptr += 4;
remaining -= 4;
}
written = min(remaining,buflen);
bcopy(buf,pkt->ioptr,written);
pkt->ioptr += written;
if(flags & ARDP_A2R_NOSPLITL) {
*(pkt->ioptr) = '\0'; /* To catch runaway strrchar */
/* Find last newline */
newline = strrchr(pkt->start + pkt->length,'\n');
if(newline) pkt->length = newline + 1 - pkt->start;
}
else pkt->length = pkt->ioptr - pkt->start;
/* Always need to stick on trailing NULL for sake of ardp_respond(),
which expects it. */
*pkt->ioptr = '\0';
/* In this case, ARDP_A@R_NOSPLITB was not specified, split it */
if(written != buflen) {
buf += written;
buflen -= written;
goto keep_writing;
}
if(flags & ARDP_A2R_COMPLETE) {
deflen = pkt->ioptr - (pkt->start + pkt->length);
/* If deferred, write a newline */
if(deflen) {
*(pkt->ioptr++) = '\n';
pkt->length = pkt->ioptr - pkt->start;
/* Always need to stick on trailing NULL for sake of
ardp_respond(), which expects it. */
*pkt->ioptr = '\0';
}
}
return ARDP_SUCCESS;
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 2/93 to send reply to request
* Hacked by swa 11/94 to send length-coded reply to request.
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
/*
* ardp_breply - send a reply to a request that might contain binary data
*
* ardp_breply reply takes request to which a reply is to be sent
* a flags field, and a message to be sent to the client in response
* to the request, and a length count for the message. ardp_breply then adds
* the response to the output queue for the request.
*
* A length count of 0 indicates that the buffer is null-terminated.
* (implementation note: by passing the 0 down to ardp_add2req, we
* allow there to be only one pass through the buffer instead of 2.)
*
* If space remains in the packet, the response is buffered pending
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
* in which case all data is sent. If the size of the buffered response
* approaches the maximum packet size, the buffered data is sent, and
* and a new packet is started to hold any remaining data from the current
* message.
*
* The lower level function (ardp_respond) assigns packet numbers and
* tags outgoing packets if necessary or a multi packet response.
*/
int
ardp_breply(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message, /* The data to be sent. */
int len) /* message length; 0 means null-terminated */
{
int tmp;
tmp = ardp_add2req(req,flags,message,len);
if (tmp) return tmp;
if(flags&ARDP_R_COMPLETE) return(ardp_respond(req,ARDP_R_COMPLETE));
/* Check to see if any packets are done */
#if 1
if(req->outpkt && req->outpkt->next) {
#else
/* This always yields the same results as the previous line but appears
clunkier to me. */
if(req->outpkt && (req->outpkt->previous != req->outpkt)) {
#endif
PTEXT tpkt; /* Temp to hold active packet */
/* Hold out final packet */
tpkt = req->outpkt->previous;
EXTRACT_ITEM(tpkt,req->outpkt);
tmp = ardp_respond(req,ARDP_R_INCOMPLETE);
APPEND_ITEM(tpkt,req->outpkt);
if (tmp) return tmp;
}
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 11/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
#include <perrno.h> /* For perrno */
/* See lib/ardp/usc_lic_str.c */
extern char *usc_license_string;
/* This is used in Prospero in lib/pfs/perrmesg.c. Change it there too if you
change it here. */
char *ardp___please_do_not_optimize_me_out_of_existence;
/* perrno is declared in ardp_perrno.c in case some older applications
have explicitly declared their own perrno variable (a practice we now
discourage). */
/* This function definition is shadowed in lib/pfs/perrmesg.c. Change it there
too if you change it here. */
void
p_clear_errors(void)
{
ardp___please_do_not_optimize_me_out_of_existence = usc_license_string;
perrno = 0;
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as get_next_request in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/time.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <pmachine.h>
extern RREQ ardp_pendingQ;
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
extern int pQNlen;
extern int pQlen;
extern int ardp_srvport;
extern int ardp_prvport;
#define max(x,y) (x > y ? x : y)
/*
* ardp_get_nxt - return next request for server
*
* ardp_get_nxt returns the next request to be processed by the server.
* If no requests are pending, ardp_get_nxt waits until a request
* arrives, then returns it.
*/
/* Called outside multithraded stuff; doesn't need to be mutexed. */
RREQ
ardp_get_nxt(void)
{
RREQ nextreq;
fd_set readfds;
int tmp;
tryagain:
if (nextreq = ardp_get_nxt_nonblocking())
return nextreq;
/* if queue is empty, then wait till somethings comes */
/* in, then go back to start */
FD_ZERO(&readfds);
if(ardp_srvport != -1) FD_SET(ardp_srvport, &readfds);
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
tmp = select(max(ardp_srvport,ardp_prvport) + 1, &readfds,
(fd_set *)0, (fd_set *)0, NULL);
goto tryagain;
}
/*
* Nonblocking version of the above.
* Returns NULL if no pending items.
*/
RREQ
ardp_get_nxt_nonblocking(void)
{
ardp_accept();
/* return next message in queue */
if (ardp_pendingQ) {
/* Atomic test; save ourselves the trouble of going through the kernel
if nothing in queue */
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
if(ardp_pendingQ) {
RREQ nextreq = ardp_pendingQ;
EXTRACT_ITEM(nextreq, ardp_pendingQ);
pQlen--;if(nextreq->priority > 0) pQNlen--;
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
nextreq->svc_start_time.tv_sec = time(NULL);
EXTERN_MUTEXED_LOCK(ardp_runQ);
APPEND_ITEM(nextreq,ardp_runQ);
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
return(nextreq);
}
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
}
return NOREQ;
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 For use in adrp_send
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() */
extern int ardp_priority; /* Override for 0 priority */
extern int pfs_debug;
/*
* ardp_headers - Add headers to packets to be sent to server
*
* ardp_headers takes pointer to a request structure and adds headers to
* all the packets in the trns list. The fields for the headers are
* taken from other fields in the request structure. If the priority is
* zero, it is taken from the global vairable ardp_priority.
*
* If ardp_headers is called more than once, subsequent calls will
* update the headers to conform to changes in the request fields.
*/
int
ardp_headers(RREQ req)
{
PTEXT ptmp; /* Temporary packet pointer */
for(ptmp = req->trns; ptmp; ptmp = ptmp->next) {
int old_hlength; /* Old header length */
int new_hlength; /* New header length, whatever it may
be. */
unsigned short ftmp; /* Temporary for values of fields */
/* Boolean: do we stamp this packet with the window size? */
/* We will add an explicity window-size stamp to the first sent, if
an explicit window size was set. This packet is the one stamped
with sequence number 1. Thus we know that the window size message
won't be lost. */
int stamp_window_size = (req->flags & ARDP_FLAG_SEND_MY_WINDOW_SIZE)
&& (ptmp->seq == 1);
int stamp_priority = (req->priority || ardp_priority)
&& (ptmp->seq == 1);
old_hlength = ptmp->text - ptmp->start;
/* XXX Should do further tests to make sure all packets present */
if(ptmp->seq == 0) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp: sequence number not set in packet\n");
fflush(stderr);
return(ARDP_BAD_REQ);
}
/* If priority stamp or explicit client window size, need octets 11 and
12 to be present. */
if (stamp_priority || stamp_window_size) {
new_hlength = 13; /* room for octets through 12 */
if(req->priority || ardp_priority)
new_hlength += 2; /* 2 octets for priority argument. */
if (stamp_window_size)
new_hlength += 2; /* 2 octets for window size */
} else {
new_hlength = 9; /* room for octets through 8 (received-through)
*/
}
/* New header length now set. */
/* Allocate space for the new header */
ptmp->start = ptmp->text - new_hlength;
ptmp->length += new_hlength - old_hlength;
/* Set the header length and version # (zeroth octet) */
/* Version # is zero in this version of the ARDP library; last 6 bytes
of octet are header length. */
*(ptmp->start) = (char) new_hlength;
/* Set octets 1 through 8 of header */
/* Connection ID (octets 1 & 2) */
bcopy2(&(req->cid),ptmp->start+1);
/* Sequence number (octets 3 & 4) */
ftmp = htons(ptmp->seq);
bcopy2(&ftmp,ptmp->start+3);
/* Total packet count (octets 5 & 6) */
ftmp = htons(req->trns_tot);
bcopy2(&ftmp,ptmp->start+5);
/* Received through (octets 7 & 8) */
ftmp = htons(req->rcvd_thru);
bcopy2(&ftmp,ptmp->start+7);
/* Now set any options. */
if (new_hlength > 9) {
char * optiondata; /* where options go. */
/* zero out octets 9 and 10 (expected time 'till response). It is
not defined for the client to specify this to the server,so
it is always zero. */
bzero2(ptmp->start + 9);
/* set octet 11 (flags) initially clear */
ptmp->start[11] = 0;
/* Here Octet 12 (option) is zero (no special options). */
ptmp->start[12] = 0;
optiondata = ptmp->start + 13; /* additional octets start here */
/* Priority */
if(stamp_priority) {
*(ptmp->start+11) |= 0x02; /* priority flag */
if(req->priority) ftmp = htons(req->priority);
else ftmp = htons(ardp_priority);
bcopy2(&ftmp, optiondata);
optiondata += 2;
}
if(stamp_window_size) {
*(ptmp->start+11) |= 0x08; /* Set window size flag */
ftmp = htons(req->window_sz);
bcopy2(&ftmp, optiondata);
optiondata += 2;
}
assert(optiondata == ptmp->start + new_hlength);
}
}
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 12/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
/* Data definition. This may be reset by any client. */
int (*internal_error_handler)(const char file[], int line, const char mesg[]) = 0;

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1993-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs_threads.h>
#include <ardp.h>
#ifdef PFS_THREADS
p_th_mutex p_th_mutexARDP_ACCEPT; /* declaration */
p_th_mutex p_th_mutexPTEXT; /* declared in ardp_mutexes.c */
p_th_mutex p_th_mutexARDP_RQALLOC; /* declared in ardp_mutexes.c */
p_th_mutex p_th_mutexGETHOSTBYNAME; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexARDP_SELFNUM; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexDNSCACHE; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexALLDNSCACHE; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexFILES; /* declared on p__self_num.c */
p_th_mutex p_th_mutexFILELOCK; /* declared in flock.c */
#endif
void
ardp_init_mutexes(void)
{
#ifdef PFS_THREADS
EXTERN_MUTEXED_INIT_MUTEX(ardp_doneQ);
EXTERN_MUTEXED_INIT_MUTEX(ardp_runQ);
p_th_mutex_init(p_th_mutexGETHOSTBYNAME);
p_th_mutex_init(p_th_mutexARDP_ACCEPT);
p_th_mutex_init(p_th_mutexPTEXT);
p_th_mutex_init(p_th_mutexARDP_RQALLOC);
p_th_mutex_init(p_th_mutexARDP_SELFNUM);
p_th_mutex_init(p_th_mutexDNSCACHE);
p_th_mutex_init(p_th_mutexALLDNSCACHE);
p_th_mutex_init(p_th_mutexFILES);
p_th_mutex_init(p_th_mutexFILELOCK);
#endif
}
#ifndef NDEBUG
void
ardp_diagnose_mutexes(void)
{
#ifdef PFS_THREADS
DIAGMUTEX(ardp_doneQ,"ardp_doneQ");
DIAGMUTEX(ardp_runQ,"ardp_runQ");
DIAGMUTEX(GETHOSTBYNAME,"GETHOSTBYNAME");
DIAGMUTEX(ARDP_ACCEPT,"ARDP_ACCEPT");
DIAGMUTEX(PTEXT,"PTEXT");
DIAGMUTEX(ARDP_RQALLOC,"ARDP_RQALLOC");
DIAGMUTEX(ARDP_SELFNUM,"ARDP_SELFNUM");
DIAGMUTEX(DNSCACHE,"DNSCACHE");
DIAGMUTEX(ALLDNSCACHE,"ALLDNSCACHE");
DIAGMUTEX(FILES,"FILES");
DIAGMUTEX(FILELOCK,"FILELOCK");
#endif
}
#endif /*NDEBUG*/

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 11/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
#include <pfs_threads.h>
#ifdef NEVERDEFINED
int perrno = 0; /* Declare it. */
#endif
EXTERN_INT_DEF(perrno);

View File

@@ -0,0 +1,420 @@
/*
* Copyright (c) 1991, 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1989-92 as part of dirsend.c in the Prospero distribution
* Modified by bcn 1/93 moved to ardp library - added asynchrony
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h> /* for bcopy() */
extern RREQ ardp_activeQ; /* Info about active requests */
extern RREQ ardp_completeQ; /* Info about completed reqs */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
int ardp_activeQ_len; /* Length of activeQ */
static struct timeval zerotime = {0, 0}; /* Used by select */
#define max(x,y) (x > y ? x : y)
static ardp__pr_ferror(int errcode);
/*
* ardp_process_active - process active requests
*
* ardp_process_active takes no arguments. It checks to see if any responses
* are pending on the UDP port, and if so processes them, adding them
* to the request structures on ardp_activeQ. If no requests are pending
* ardp_process_active processes and requests requiring retries then
* returns.
*
*/
int
ardp_process_active()
{
fd_set readfds; /* Used for select */
struct sockaddr_in from; /* Reply received from */
int from_sz; /* Size of address structure */
int hdr_len; /* Header Length */
char *ctlptr; /* Pointer to control field */
unsigned short cid = 0; /* Connection ID from rcvd pkt */
unsigned char rdflag11; /* First byte of flags (bit vect)*/
unsigned char rdflag12; /* Second byte of flags (int) */
unsigned char tchar; /* For decoding extra fields */
unsigned short stmp; /* Temp short for conversions */
unsigned long ltmp; /* Temp long for converions */
int tmp; /* Temporaty return value */
int nr; /* Number octest received */
long now; /* The current time */
RREQ req = NOREQ; /* To store request info */
PTEXT pkt = NOPKT; /* Packet being processed */
PTEXT ptmp = NOPKT; /* Packet being processed */
assert(P_IS_THIS_THREAD_MASTER()); /* something_received not MT-Safe */
check_for_pending:
/* Set list of file descriptors to be checked by select */
FD_ZERO(&readfds);
FD_SET(ardp_port, &readfds);
/* select - either recv is ready, or not */
/* see if timeout or error or wrong descriptor */
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, &zerotime);
/* If tmp is zero, then nothing to process, check for timeouts */
if(tmp == 0) {
now = time(NULL);
req = ardp_activeQ;
while(req) {
if (req->status == ARDP_STATUS_ACKPEND) {
ardp_xmit(req, -1 /* just ACK; send no data packets */);
req->status = ARDP_STATUS_ACTIVE;
}
if((req->wait_till.tv_sec) && (now >= req->wait_till.tv_sec)) {
if(req->retries_rem-- > 0) {
req->timeout_adj.tv_sec = ARDP_BACKOFF(req->timeout_adj.tv_sec);
if (pfs_debug >= 8) {
fprintf(stderr,"Connection %d timed out - Setting timeout to %d seconds.\n",
ntohs(req->cid), (int) req->timeout_adj.tv_sec);
}
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
ardp_xmit(req, req->pwindow_sz);
} else {
if(pfs_debug >= 8) {
fprintf(stderr,"Connection %d timed out - Retry count exceeded.\n",
ntohs(req->cid) );
(void) fflush(stderr);
}
req->status = ARDP_TIMEOUT;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
}
}
req = req->next;
}
return(ARDP_SUCCESS);
}
/* If negative, then return an error */
if((tmp < 0) || !FD_ISSET(ardp_port, &readfds)) {
if (pfs_debug)
fprintf(stderr, "select failed : returned %d port=%d\n",
tmp, ardp_port);
return(ardp__pr_ferror(ARDP_SELECT_FAILED));
}
/* Process incoming packets */
pkt = ardp_ptalloc();
pkt->start = pkt->dat;
from_sz = sizeof(from);
if ((nr = recvfrom(ardp_port, pkt->start, sizeof(pkt->dat),
0, &from, &from_sz)) < 0) {
if (pfs_debug) perror("recvfrom");
ardp_ptlfree(pkt);
return(ardp__pr_ferror(ARDP_BAD_RECV));
}
pkt->length = nr;
*(pkt->start + pkt->length) = '\0';
if (pfs_debug >= 6)
fprintf(stderr,"Received packet from %s\n", inet_ntoa(from.sin_addr));
/* If the first byte is greater than 31 we have an old version */
/* response - return error */
if((hdr_len = (unsigned char) *(pkt->start)) > 31) {
ardp_ptfree(pkt);
if(ardp_activeQ->next == NOREQ)
return(ardp__pr_ferror(ARDP_BAD_VERSION));
else goto check_for_pending;
}
/* For the current format, the first two bits are a version number */
/* and the next six are the header length (including the first byte). */
ctlptr = pkt->start + 1;
if(hdr_len >= 3) { /* Connection ID */
bcopy2(ctlptr,&stmp);
if(stmp) cid = stmp;
ctlptr += 2;
}
/* Match up response with request */
req = ardp_activeQ;
while(req) {
if(cid == req->cid) break;
req = req->next;
}
if(!req) { /* The request isn't on the active queue */
if (pfs_debug>=6)
fprintf(stderr,"Packet received for inactive request (cid %d)\n",
ntohs(cid));
ardp_ptfree(pkt);
/* The following can be removed when old servers are gone */
if((cid == 0) && (ardp_activeQ->next == NOREQ))
return(ardp__pr_ferror(ARDP_BAD_VERSION));
goto check_for_pending;
}
if(hdr_len >= 5) { /* Packet number */
bcopy2(ctlptr,&stmp);
pkt->seq = ntohs(stmp);
ctlptr += 2;
}
else { /* No packet number specified, so this is the only one */
pkt->seq = 1;
req->rcvd_tot = 1;
}
if(hdr_len >= 7) { /* Total number of packets */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) req->rcvd_tot = ntohs(stmp);
ctlptr += 2;
}
if(hdr_len >= 9) { /* Receievd through */
bcopy2(ctlptr,&stmp); /* 1 means received request */
req->prcvd_thru = max(ntohs(stmp),req->prcvd_thru);
ctlptr += 2;
}
if(hdr_len >= 11) { /* Service requested wait */
bcopy2(ctlptr,&stmp);
if(stmp || (req->svc_rwait != ntohs(stmp))) {
now = time(NULL);
/* New or non-zero requested wait value */
req->svc_rwait = ntohs(stmp);
if(pfs_debug >= 8)
fprintf(stderr,"Service asked us to wait %d seconds\n",
req->svc_rwait);
/* Adjust out timeout */
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
/* Reset the retry count */
req->retries_rem = req->retries;
}
ctlptr += 2;
}
if(hdr_len >= 12) { /* Flags (1st byte) */
bcopy1(ctlptr,&rdflag11);
if(rdflag11 & 0x80) {
if(pfs_debug >= 8)
fprintf(stderr,"Ack requested\n");
req->status = ARDP_STATUS_ACKPEND;
}
if(rdflag11 & 0x40) {
if(pfs_debug >= 8)
fprintf(stderr,"Sequenced control packet\n");
pkt->length = -1;
}
ctlptr += 1;
}
if(hdr_len >= 13) { /* Flags (2nd byte) */
/* Reserved for future use */
bcopy1(ctlptr,&rdflag12);
ctlptr += 1;
if(rdflag12 == 2) {
/* Attempt to set back prcvd_thru */
bcopy2(pkt->start+7,&stmp);
req->prcvd_thru = ntohs(stmp);
}
if(rdflag12 == 1) {
/* ARDP Connection Refused */
if(pfs_debug >= 8)
fprintf(stderr,"***ARDP connection refused by server***\n");
req->status = ARDP_REFUSED;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
goto check_for_pending;
}
if(rdflag12 == 4) {
/* Server Redirect */
bcopy4(ctlptr,&(req->peer_addr));
ctlptr += 4;
bcopy2(ctlptr,&(req->peer_port));
ctlptr += 2;
if(pfs_debug >= 8)
fprintf(stderr,"***ARDP redirect to %s(%d)***\n",
inet_ntoa(req->peer_addr),PEER_PORT(req));
ardp_xmit(req, req->pwindow_sz);
}
if(rdflag12 == 254) {
tchar = *ctlptr;
ctlptr++;
if(tchar & 0x1) { /* Queue position */
bcopy2(ctlptr,&stmp);
req->inf_queue_pos = ntohs(stmp);
if(pfs_debug >= 8)
fprintf(stderr,"Current queue position on server is %d\n",
req->inf_queue_pos);
ctlptr += 2;
}
if(tchar & 0x2) { /* Expected system time */
bcopy4(ctlptr,&ltmp);
req->inf_sys_time = ntohl(ltmp);
if(pfs_debug >= 8)
fprintf(stderr,"Expected system time is %d seconds\n",
req->inf_sys_time);
ctlptr += 4;
}
}
}
/* If ->seq 0, then an unsequenced control packet */
if(pkt->seq == 0) {
ardp_ptfree(pkt);
goto check_for_pending;
}
if(pkt->length >= 0) pkt->length -= hdr_len;
pkt->start += hdr_len;
pkt->text = pkt->start;
pkt->ioptr = pkt->start;
if(pfs_debug >= 8) fprintf(stderr,"Packet %d of %d (cid=%d)\n", pkt->seq,
req->rcvd_tot, ntohs(req->cid));
if (req->rcvd == NOPKT) {
/* Add it as the head of empty doubly linked list */
req->rcvd = pkt;
pkt->previous = pkt;
if(pkt->seq == 1) {
req->comp_thru = pkt;
req->rcvd_thru = 1;
/* If only one packet, then return it. We will assume */
/* that it is not a sequenced control packet */
if(req->rcvd_tot == 1) goto req_complete;
}
goto ins_done;
}
if(req->comp_thru && (pkt->seq <= req->rcvd_thru))
ardp_ptfree(pkt); /* Duplicate */
else if(pkt->seq < req->rcvd->seq) { /* First (sequentially) */
pkt->next = req->rcvd;
pkt->previous = req->rcvd->previous;
req->rcvd->previous = pkt;
req->rcvd = pkt;
if(req->rcvd->seq == 1) {
req->comp_thru = req->rcvd;
req->rcvd_thru = 1;
}
}
else { /* Insert later in the packet list unless duplicate */
ptmp = (req->comp_thru ? req->comp_thru : req->rcvd);
while (pkt->seq > ptmp->seq) {
if(ptmp->next == NULL) {
/* Insert at end */
ptmp->next = pkt;
pkt->previous = ptmp;
pkt->next = NULL;
req->rcvd->previous = pkt;
goto ins_done;
}
ptmp = ptmp->next;
}
if(ptmp->seq == pkt->seq) /* Duplicate */
ardp_ptfree(pkt);
else { /* insert before ptmp (we know were not first) */
ptmp->previous->next = pkt;
pkt->previous = ptmp->previous;
pkt->next = ptmp;
ptmp->previous = pkt;
}
}
ins_done:
/* Find out how much is complete and remove sequenced control packets */
while(req->comp_thru && req->comp_thru->next &&
(req->comp_thru->next->seq == (req->comp_thru->seq + 1))) {
/* We have added one more in sequence */
if(pfs_debug >= 8)
fprintf(stderr,"Packets now received through %d\n",
req->comp_thru->next->seq);
if(req->comp_thru->length == -1) {
/* Old comp_thru was a sequenced control packet */
ptmp = req->comp_thru;
req->comp_thru = req->comp_thru->next;
req->rcvd_thru = req->comp_thru->seq;
EXTRACT_ITEM(ptmp,req->rcvd);
ardp_ptfree(ptmp);
}
else {
/* Old comp_thru was a data packet */
req->comp_thru = req->comp_thru->next;
req->rcvd_thru = req->comp_thru->seq;
}
/* Update outgoing packets */
ardp_headers(req);
/* We've made progress, so reset timeout and retry count */
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
req->retries_rem = req->retries;
}
/* See if there are any gaps - possibly toggle GAP status */
if(!req->comp_thru || req->comp_thru->next) {
if (req->status == ARDP_STATUS_ACTIVE) req->status = ARDP_STATUS_GAPS;
}
else if (req->status == ARDP_STATUS_GAPS) req->status = ARDP_STATUS_ACTIVE;
/* If incomplete, wait for more */
if (!(req->comp_thru) || (req->comp_thru->seq != req->rcvd_tot))
goto check_for_pending;
req_complete:
if (pfs_debug >= 7) {
fprintf(stderr,"The complete response has been received.\n");
(void) fflush(stderr);
}
if(req->status == ARDP_STATUS_ACKPEND) {
if (pfs_debug >= 7) {
if (req->peer.sin_family == AF_INET)
fprintf(stderr,"Acknowledging final packet to %s(%d)\n",
inet_ntoa(req->peer_addr), PEER_PORT(req));
else fprintf(stderr,"Acknowledging final packet\n");
(void) fflush(stderr);
}
ardp_xmit(req, req->pwindow_sz);
}
req->status = ARDP_STATUS_COMPLETE;
req->inpkt = req->rcvd;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
return(ARDP_SUCCESS);
}
static int
ardp__pr_ferror(int errcode)
{
RREQ creq;
while(ardp_activeQ) {
creq = ardp_activeQ;
ardp_activeQ->status = errcode;
EXTRACT_ITEM(creq,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(creq,ardp_completeQ);
}
perrno = errcode;
return(errcode);
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1989-91 as part of the Prospero distribution
* Modified by bcn 1/93 changed to conform to ardp.h
* Modified by swa 12/93 threads added.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <ardp.h>
#include <stdlib.h> /* For malloc or free */
#include <pfs_threads.h>
#include <mitra_macros.h>
/* "free" conflicted with free() - Mitra */
static PTEXT lfree = NOPKT; /* locked with p_th_mutexPTEXT */
int ptext_count = 0;
int ptext_max = 0;
/*
* ardp_ptalloc - allocate and initialize ptext structure
*
* ardp_ptalloc returns a pointer to an initialized structure of type
* PTEXT. If it is unable to allocate such a structure, it
* returns NULL (NOPKT).
*/
PTEXT
ardp_ptalloc()
{
PTEXT pt;
TH_STRUC_ALLOC(ptext,PTEXT,pt);
/* Initialize and fill in default values. */
pt->seq = 0;
pt->length = 0;
/* The offset is to leave room for additional headers */
pt->start = pt->dat + ARDP_PTXT_HDR;
pt->text = pt->start;
pt->ioptr = pt->start;
pt->mbz = 0;
return(pt);
}
/*
* ardp_ptfree - free a PTEXT structure
*
* ardp_ptfree takes a pointer to a PTEXT structure and adds it to
* the free list for later reuse.
*/
void ardp_ptfree(pt)
PTEXT pt;
{
TH_STRUC_FREE(ptext,PTEXT,pt);
}
/*
* ardp_ptlfree - free a PTEXT structure
*
* ardp_ptlfree takes a pointer to a PTEXT structure frees it and any linked
* PTEXT structures. It is used to free an entrie list of PTEXT
* structures.
*/
void ardp_ptlfree(pt)
PTEXT pt;
{
TH_STRUC_LFREE(PTEXT,pt,ardp_ptfree);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 2/93 to send reply to request
* Gutted by swa 11/93 functionality moved to ardp_breply().
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
/*
* ardp_reply - send a null-terminated string as a reply to a request
*
* ardp_reply reply takes request to which a reply is to be sent
* a flags field, and a message to be sent to the client in response
* to the request. ardp_reply then calls ardp_reply() to do the work.
*
* If space remains in the packet, the response is buffered pending
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
* in which case all data is sent. If the size of the buffered response
* approaches the maximum packet size, the buffered data is sent, and
* and a new packet is started to hold any remaining data from the current
* message. (This is implemented by ardp_breply()).
*/
int
ardp_reply(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message) /* The data to be sent */
{
return ardp_breply(req, flags, message, 0);
}

View File

@@ -0,0 +1,471 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1991 as transmit in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() */
#include <plog.h>
EXTERN_MUTEXED_DECL(RREQ,ardp_doneQ);
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
extern int ardp_srvport;
extern int ardp_prvport;
extern int dQlen; /* mutexed with ardp_doneQ */
extern int dQmaxlen;
int ardp_clear_doneQ_loginfo = 0; /* Clear log info from the doneQ.
Set by the -n option to
dirsrv. */
/*
* ardp_respond - respond to request
*
* ardp_respond takes a request block whose ->outpkt element is a pointer
* to a list of packets that have not yet been returned. It moves the
* packets to the transmission queue of the request (->trns) and assigns a
* sequence number to each packet. If options is ARDP_R_COMPLETE, it
* also sets the ->trns_tot field of the request indicating the total
* number of packets in the response. if the ARDP_R_NOSEND option is
* not specified, the current packet is also sent to the client.
*
* ardp_respond() expects the text of the packet to have a trailing null
* at the end of it, which is transmitted for safety's sake.
* (noted: swa, 8/5/93). This explains some bugs...
*/
int
ardp_respond(req, options)
RREQ req;
int options;
{
char buf[ARDP_PTXT_DSZ];
int sent;
int retval = ARDP_SUCCESS; /* Return value */
unsigned short cid = htons(req->cid);
unsigned short nseq = 0;
unsigned short ntotal = 0;
unsigned short rcvdthru = 0;
unsigned short bkoff = 0;
PTEXT tpkt; /* Temporary pkt pointer */
*buf = '\0';
if(req->peer_ardp_version < 0) cid = 0;
if(req->status == ARDP_STATUS_FREE)
internal_error("Attempt to respond to free RREQ\n");
if(!req->outpkt) return(ARDP_BAD_REQ);
more_to_process:
if(!req->trns) req->outpkt->seq = 1;
else req->outpkt->seq = req->trns->previous->seq + 1;
if((options & ARDP_R_COMPLETE) && (req->outpkt->next == NOPKT)) {
/* It's the last packet to send. */
req->trns_tot = req->outpkt->seq; /* set the total # of packets; now
known. */
/* Test this condition later to see if the server (us) needs to request
that the client ACK. The server will request an ACK if we had
previously told the client to back off and now are rescinding that.
*/
}
nseq = htons((u_short) req->outpkt->seq);
ntotal = htons((u_short) req->trns_tot);
if((req->peer_ardp_version < 0)&&(req->peer_ardp_version != -2)) {
if(req->trns_tot) sprintf(buf, "MULTI-PACKET %d OF %d",
req->outpkt->seq, req->trns_tot);
else sprintf(buf,"MULTI-PACKET %d\n",req->outpkt->seq);
}
/* Note that in the following, we don't have to make sure */
/* there is room for the header in the packet because we */
/* are the only one that moves back the start, and ptalloc */
/* allocates space for us in all packets it creates */
/* If a single message and no connection ID to return, */
/* and no pending server requested wait pending then */
/* we can leave the control fields out */
if((req->trns_tot == 1) && (req->svc_rwait == 0)) {
/* Once V4 clients gone, the next if condition can be removed */
if((req->peer_ardp_version > -1)||(req->peer_ardp_version == -2)) {
if(req->cid == 0) {
req->outpkt->start -= 1;
req->outpkt->length += 1;
*req->outpkt->start = (char) 1;
}
else {
req->outpkt->start -= 3;
req->outpkt->length += 3;
*req->outpkt->start = (char) 3;
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
}
}
}
/* Fill in the control fields */
else {
/* For old versions, assume that svc_rwait of > 5 is too long. */
/* For new versions, if we set the svc_rwait before to any non-default
value, now set it to 0. (client's default). */
/* if we might have to set octet 11 flags (in this case, the ACK flag),
then we need to send an 11-byte request.
This is the case either:
(a) if we need to clear a service requested wait or
(b) if we are sending the last packet of a window, so that the
client should ACK (or request a retry) before the next one goes.
*/
if (/* Case (A) -- clear wait */
((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|| (req->peer_ardp_version == 0 && req->svc_rwait)
|| (req->svc_rwait_seq > req->prcvd_thru))
|| /* Case (B) -- sending last packet of a window */
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
req->outpkt->start -= 12;
req->outpkt->length += 12;
*req->outpkt->start = (char) 12;
rcvdthru = htons((u_short) req->rcvd_thru);
bcopy2(&rcvdthru,req->outpkt->start+7); /* Recvd Through */
/* XXX Note that when all clients V5, new wait will be 0 */
/* Assume we should cancel the wait and remember when reset */
if((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|| (req->peer_ardp_version == 0 && req->svc_rwait)) {
if(req->peer_ardp_version < 0)
req->svc_rwait = 5;
else
req->svc_rwait = 0;
req->svc_rwait_seq = req->outpkt->seq; /* This was the sequence
number it was reset
on. */
/* We'll ask for an acknowledgement when we send the last
packet of the response. */
}
bkoff = htons((u_short) req->svc_rwait);
bcopy2(&bkoff,req->outpkt->start+9); /* New ttwait */
/* Send an ACK IF: */
if ((/* (A1) It's the last packet */
(req->trns_tot && req->outpkt->seq == req->trns_tot)
&& /* (A2) If we reduced a previously requested wait, and haven't
yet had that reduction acknowledged, then ask for an
acknowledgement. */
(req->svc_rwait_seq > req->prcvd_thru))
|| /* OR: Case (B) -- sending last packet of a window */
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
req->retries_rem = 4;
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
*(req->outpkt->start+11) = 0x80; /* Request ack */
} else {
*(req->outpkt->start+11) = 0x00; /* Don't request ack */
}
}
else {
req->outpkt->start -= 7;
req->outpkt->length += 7;
*req->outpkt->start = (char) 7;
}
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
bcopy2(&nseq,req->outpkt->start+3); /* Pkt no */
bcopy2(&ntotal,req->outpkt->start+5); /* Total */
}
#if 0
/* commented out by swa@isi.edu, since nulls in packets are now significant
to the ARDP library. Therefore, one should NOT be appended to each
packet in the data area. */
/* Make room for the trailing null */
req->outpkt->length += 1;
#endif
/* Only send if packet not yet received. */
/* Do honor the window of req->pwindow_sz packets. */
if((!(options & ARDP_R_NOSEND)) &&
(req->outpkt->seq <= (req->prcvd_thru + req->pwindow_sz)) &&
(req->outpkt->seq > req->prcvd_thru) /* This packet not yet received */
) {
retval = ardp_snd_pkt(req->outpkt,req);
}
/* Add packet to req->trns */
tpkt = req->outpkt;
EXTRACT_ITEM(tpkt,req->outpkt);
APPEND_ITEM(tpkt,req->trns);
if(req->outpkt) goto more_to_process;
/* If complete then add request structure to done */
/* queue in case we have to retry. */
if(options & ARDP_R_COMPLETE) {
RREQ match_in_runQ; /* Variable for indexing ardp_runQ */
/* Request has been processed, here you can accumulate */
/* statistics on system time or service time */
plog(L_QUEUE_COMP, req, "Requested service completed");
arch_set_etime(req); /* bajan */
EXTERN_MUTEXED_LOCK(ardp_runQ);
for (match_in_runQ = ardp_runQ; match_in_runQ; match_in_runQ = match_in_runQ->next) {
if(match_in_runQ == req) {
EXTRACT_ITEM(req, ardp_runQ);
break;
}
}
/* At this point, 'req' is the completed request structure. It is
definitely not on the ardp_runQ, and if it was, it's been removed.
*/
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
if((req->cid == 0) || (dQmaxlen <= 0)) {
/* If request has no CID (can't be matched on a retry) or
if done-Q max length is <= 0 (i.e., don't keep a doneQ), then
just throw away the request now that it's done. --swa */
#if 0 /* ask BCN about this. Should never be
necessary, since req->outpkt is always going
to be NULL or we wouldn't be here. */
req->outpkt = NULL;
#endif
ardp_rqfree(req);
}
else {
/* This item should be put on the doneQ; don't just throw it away.
*/
/* Note that this code will not handle a reduction in the size of
dQmaxlen; if anywhere you reset it to a smaller value, that code
will have to truncate the queue. */
EXTERN_MUTEXED_LOCK(ardp_doneQ);
if(dQlen <= dQmaxlen) {
/* Add to start */
#ifndef NDEBUG /* this helps debugging and slightly cuts down
on memory usage of the doneq. */
if (ardp_clear_doneQ_loginfo)
ardp_rq_partialfree(req);
#endif
PREPEND_ITEM(req, ardp_doneQ);
dQlen++;
} else {
/* The last item in the queue is ardp_doneQ->previous. */
/* Use a variable to denote it, so that the EXTRACT_ITEM macro
doesn't encounter problems (since it internally modifies the
referent of the name ardp_doneQ->previous). */
register RREQ doneQ_lastitem = ardp_doneQ->previous;
/* Add new request to start */
#ifndef NDEBUG /* this helps debugging and slightly cuts down
on memory usage of the doneq. */
if (ardp_clear_doneQ_loginfo)
ardp_rq_partialfree(req);
#endif
PREPEND_ITEM(req, ardp_doneQ);
/* Now, prepare to remove the last item in the queue */
/* If the request to remove was not acknowledged by the
clients, log the fact */
if(doneQ_lastitem->svc_rwait_seq >
doneQ_lastitem->prcvd_thru) {
plog(L_QUEUE_INFO,doneQ_lastitem,
"Requested ack never received (%d of %d/%d ack)",
doneQ_lastitem->prcvd_thru,
doneQ_lastitem->svc_rwait_seq,
doneQ_lastitem->trns_tot);
}
/* Now do the removal and free it. */
EXTRACT_ITEM(doneQ_lastitem, ardp_doneQ);
ardp_rqfree(doneQ_lastitem);
}
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
}
}
return(retval);
}
/*
* ardp_rwait - sends a message to a client requesting
* that it wait for service. This message indicates that
* there may be a delay before the request can be processed.
* The recipient should not attempt any retries until the
* time specified in this message has elapsed. Depending on the
* protocol version in use by the client, the additional
* queue position and system time arguments may be returned.
*/
int
ardp_rwait(RREQ req, /* Request to which this is a reply */
int timetowait, /* How long client should wait */
short qpos, /* Queue position */
/* Note stime is a System call in solaris, changed to systemtime */
int systemtime) /* System time */
{
PTEXT r = ardp_ptalloc();
short cid = htons(req->cid);
short nseq = 0;
short zero = 0;
short backoff;
short stmp;
int ltmp;
int tmp;
if(req->peer_ardp_version < 0) cid = 0;
/* Remember that we sent a server requested wait and assume */
/* it took effect, though request will be unsequenced */
/* This seems bogus to me. Rather, more appropriate would be to send an
unsequenced control packet if the requested wait is being extended and
a sequenced packet if the wait is being shortened, since the shortening
of the wait is an event which requires an acknowledgement. */
/* Note, however, that this shortening is a way the current function is not
used. */
req->svc_rwait_seq = req->prcvd_thru; /* Mark the latest requested wait as
definitely having been received.
This is not necessary, actually --
leaving this set to zero is ok. */
req->svc_rwait = timetowait;
*r->start = (char) 11;
r->length = 11;
backoff = htons((u_short) timetowait);
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&nseq,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&zero,r->start+7); /* Received through */
bcopy2(&backoff,r->start+9); /* Backoff */
if((req->peer_ardp_version >= 0) && (qpos || systemtime)) {
r->length = 14;
bzero3(r->start+11);
*(r->start+12) = (unsigned char) 254;
if(qpos) *(r->start+13) |= (unsigned char) 1;
if(systemtime) *(r->start+13) |= (unsigned char) 2;
if(qpos) {
stmp = htons(qpos);
bcopy2(&stmp,r->start+r->length);
r->length += 2;
}
if(systemtime) {
ltmp = htonl(systemtime);
bcopy4(&ltmp,r->start+r->length);
r->length += 4;
}
*r->start = (char) r->length;
}
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_refuse - sends a message to the recipient indicating
* that its connection attempt has been refused.
*/
int
ardp_refuse(RREQ req)
{
PTEXT r;
short cid = htons(req->cid);
short zero = 0;
int tmp;
/* If old version won't understand refused */
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
r = ardp_ptalloc();
*r->start = (char) 13;
r->length = 13;
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&zero,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&zero,r->start+7); /* Received through */
bcopy2(&zero,r->start+9); /* Backoff */
bzero2(r->start+11); /* Flags */
*(r->start + 12) = (unsigned char) 1; /* Refused */
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_redirect - sends a message to the recipient indicating that
* all unacknowledged packets should be sent to a new target destination.
* The target specifies the host address and the UDP port in network
* byte order. For now, redirections should only occur before any
* request packets have been acknowledged, or response packets sent.
*/
int
ardp_redirect(RREQ req, /* Request to be redirected */
struct sockaddr_in *target) /* Address of new server */
{
PTEXT r;
short cid = htons(req->cid);
int tmp;
/* Old versions don't support redirection */
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
r = ardp_ptalloc();
*r->start = (char) 19;
r->length = 19;
bcopy2(&cid,r->start+1); /* Connection ID */
bzero(r->start+3,9); /* Pktno, total, rcvd, swait, flags1 */
*(r->start + 12) = '\004'; /* Redirect option */
bcopy4(&(target->sin_addr),r->start+13);
bcopy2(&(target->sin_port),r->start+17);
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_ack - sends an acknowledgment message to the client indicating
* that all packets through req->rcvd_thru have been recived. It is
* only called on receipt of a multi-packet server request.
*/
int
ardp_acknowledge(RREQ req) /* Request to which this is a reply */
{
PTEXT r = ardp_ptalloc();
short cid = htons(req->cid);
short rcvd = htons(req->rcvd_thru);
short zero = 0;
int tmp;
*r->start = (char) 9;
r->length = 9;
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&zero,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&rcvd,r->start+7); /* Received through */
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to check and/or wait for completion of request
*/
#include <usc-copyr.h>
#include <stdio.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h>
extern RREQ ardp_activeQ; /* Info about active requests */
extern RREQ ardp_completeQ;/* Info about completed reqs */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
/*
* ardp_retrieve - check and/or wait for completion of request
*
* ardp_retrieve takes a request and a time to wait. It will check to
* see if the request is complete and if so, returns ARDP_SUCCESS.
* If not complete, ardp_retrieve will wait up till the time to wait
* before returning. If still incomplete it will return ARDP_PENDING.
* A time to wait of -1 indicates that one should not return until
* complete, or until a timeout occurs. On any failure (other than
* still pending), an error code is returned.
*
* BUGS: Right now, only accepts ttwait values of 0 and -1. If
* positive, it is currently treated as -1.
*/
int
ardp_retrieve(req,ttwait)
RREQ req; /* Request to wait for */
int ttwait; /* Time to wait in microseconds */
{
fd_set readfds; /* Used for select */
struct timeval *selwait; /* Time to wait for select */
int tmp; /* Hold value returned by select */
/* XXX For now only support ttwait values of 0 and -1 */
if(ttwait > 0) return(ARDP_FAILURE);
p_clear_errors();
if(req->status == ARDP_STATUS_FREE) {
fprintf(stderr,"Attempt to retrieve free RREQ\n");
abort();
return(ARDP_BAD_REQ);
}
if(req->status == ARDP_STATUS_NOSTART) {
perrno = ARDP_BAD_REQ;
return(perrno);
}
check_for_more:
ardp_process_active();
if((req->status == ARDP_STATUS_COMPLETE) || (req->status > 0)) {
EXTRACT_ITEM(req,ardp_completeQ);
if(pfs_debug >= 9) {
PTEXT ptmp; /* debug-step through req->rcvd */
if(req->status > 0) fprintf(stderr,"Request failed (error %d)!",
req->status);
else fprintf(stderr,"Packets received...");
ptmp = req->rcvd;
while(ptmp) {
fprintf(stderr,"Packet %d:\n",ptmp->seq);
ardp_showbuf(ptmp->start, ptmp->length, stderr);
putc('\n', stderr);
ptmp = ptmp->next;
}
(void) fflush(stderr);
}
if(req->status == ARDP_STATUS_COMPLETE) return(ARDP_SUCCESS);
else {
perrno = req->status; /* Specific error */
return(perrno);
}
}
if(ttwait == 0) return(ARDP_PENDING);
/* Here we should figure out how long to wait, a minimum of */
/* ttwait, or the first retry timer for any pending request */
/* For the time being, we use the retry timer of the */
/* current request. */
if (pfs_debug >= 6) fprintf(stderr,"Waiting for reply...");
FD_ZERO(&readfds);
FD_SET(ardp_port, &readfds);
selwait = &(req->timeout_adj);
/* select - either recv is ready, or timeout */
/* see if timeout or error or wrong descriptor */
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, selwait);
/* Packet received, or timeout - both handled by ardp_process_active */
if(tmp >= 0) goto check_for_more;
if (pfs_debug) fprintf(stderr, "select failed: returned %d\n", tmp);
perrno = ARDP_SELECT_FAILED;
return(perrno);
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as part of the Prospero distribution
* Modified by bcn 1/93 extended rreq structure
* Modified by swa 11/93 multithreaded
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
#include <stdlib.h> /* malloc or free */
#include <pmachine.h> /* for bzero() */
#include <pfs.h> /* for pafree and stfree */
/* When debugging the ARDP window flow control stuff, use these definitions. */
/* Defaults are set here. */
#if 0
#define ARDP_MY_WINDOW_SZ 2 /* Our window size;currently only implemented on
the client. Here, the client asks for a
window size of 2, for testing. */
#undef ARDP_DEFAULT_WINDOW_SZ /* Peer window size the server will use for its
default flow-control strategy. */ */
#define ARDP_DEFAULT_WINDOW_SZ 1 /* for testing. */
#endif
static ardp_default_timeout = ARDP_DEFAULT_TIMEOUT;
static ardp_default_retry = ARDP_DEFAULT_RETRY;
int ardp_priority = 0; /* Default priority */
static RREQ lfree = NOREQ;
int rreq_count = 0;
int rreq_max = 0;
#ifndef NDEBUG
static int rreq_member_of_list(RREQ rr, RREQ list);
#endif
extern RREQ ardp_pendingQ, ardp_runQ, ardp_doneQ;
/*
* rralloc - allocate and initialize an rreq structure
*
* ardp_rqalloc returns a pointer to an initialized structure of type
* RREQ. If it is unable to allocate such a structure, it
* returns NOREQ (NULL).
*/
RREQ
ardp_rqalloc()
{
RREQ rq;
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
if(lfree) {
rq = lfree;
lfree = lfree->next;
}
else {
rq = (RREQ) malloc(sizeof(RREQ_ST));
if (!rq) return(NOREQ);
rreq_max++;
}
rreq_count++;
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
rq->status = ARDP_STATUS_NOSTART;
#ifdef ARDP_MY_WINDOW_SZ
rq->flags = ARDP_FLAG_SEND_MY_WINDOW_SIZE; /* used by clients. */
#else
rq->flags = 0;
#endif
rq->cid = 0;
rq->priority = ardp_priority;
rq->pf_priority = 0;
rq->peer_ardp_version = 0;
rq->inpkt = NOPKT;
rq->rcvd_tot = 0;
rq->rcvd = NOPKT;
rq->rcvd_thru = 0;
#ifdef ARDP_MY_WINDOW_SZ /* This sets the window size we'll ask for */
rq->window_sz = ARDP_MY_WINDOW_SZ;
#else
rq->window_sz = 0;
#endif
rq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ; /* sets the window size we assume
our peer will accept in the
absence of an explicit
request. */
rq->comp_thru = NOPKT;
rq->outpkt = NOPKT;
rq->trns_tot = 0;
rq->trns = NOPKT;
rq->prcvd_thru = 0;
bzero(&(rq->peer),sizeof(rq->peer));
rq->rcvd_time.tv_sec = 0;
rq->rcvd_time.tv_usec = 0;
rq->svc_start_time.tv_sec = 0;
rq->svc_start_time.tv_usec = 0;
rq->svc_comp_time.tv_sec = 0;
rq->svc_comp_time.tv_usec = 0;
rq->timeout.tv_sec = ardp_default_timeout;
rq->timeout.tv_usec = 0;
rq->timeout_adj.tv_sec = ardp_default_timeout;
rq->timeout_adj.tv_usec = 0;
rq->wait_till.tv_sec = 0;
rq->wait_till.tv_usec = 0;
rq->retries = ardp_default_retry;
rq->retries_rem = ardp_default_retry;
rq->svc_rwait = 0;
rq->svc_rwait_seq = 0;
rq->inf_queue_pos = 0;
rq->inf_sys_time = 0;
#ifdef PROSPERO
rq->auth_info = NULL;
#endif /* PROSPERO */
rq->client_name = NULL;
rq->peer_sw_id = NULL;
rq->cfunction = NULL;
rq->cfunction_args = NULL;
rq->previous = NOREQ;
rq->next = NOREQ;
return(rq);
}
/*
* ardp_rqfree - free a RREQ structure
*
* ardp_rqfree takes a pointer to a RREQ structure and adds it to
* the free list for later reuse.
*/
void ardp_rqfree(rq)
RREQ rq;
{
#ifndef NDEBUG
/* This is different from the way we do consistency checking in the PFS
library, because here the status field is just sitting to be used. */
assert(rq->status != ARDP_STATUS_FREE);
rq->status = ARDP_STATUS_FREE;
CHECK_OFFLIST(rq); /* MITRA macro; probably does the same as those
listed below. Might never be defined. */
assert(!rreq_member_of_list(rq, ardp_pendingQ));
assert(!rreq_member_of_list(rq, ardp_runQ));
assert(!rreq_member_of_list(rq, ardp_doneQ));
#endif
/* Don't free inpkt or comp_thru, already on rcvd */
if(rq->rcvd) ardp_ptlfree(rq->rcvd);
/* But outpkt has not been added to trns */
if(rq->outpkt) ardp_ptlfree(rq->outpkt);
if(rq->trns) ardp_ptlfree(rq->trns);
#ifdef PROSPERO
if (rq->auth_info) pafree(rq->auth_info);
#endif /* PROSPERO */
if (rq->client_name) stfree(rq->client_name);
if (rq->peer_sw_id) stfree(rq->peer_sw_id);
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
rq->next = lfree;
rq->previous = NOREQ;
lfree = rq;
rreq_count--;
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
}
#ifndef NDEBUG
/* Free just the fields that are needed only while processing the request
but not the fields that will be used for a request that is on the ardp_doneQ
so that the results can be retransmitted. This is only needed when
debugging the server. It is used in ardp_respond() and is #ifdef'd NDEBUG.
*/
void
ardp_rq_partialfree(RREQ rq)
{
#ifdef PROSPERO
if (rq->auth_info) { pafree(rq->auth_info); rq->auth_info = NULL; }
#endif /* PROSPERO */
if (rq->client_name) { stfree(rq->client_name); rq->client_name = NULL; }
if (rq->peer_sw_id) { stfree(rq->peer_sw_id); rq->peer_sw_id = NULL; }
}
#endif
/*
* ardp_rqlfree - free many RREQ structures
*
* ardp_rqlfree takes a pointer to a RREQ structure frees it and any linked
* RREQ structures. It is used to free an entrie list of RREQ
* structures.
*/
void
ardp_rqlfree(rq)
RREQ rq;
{
RREQ nxt;
while(rq != NOREQ) {
nxt = rq->next;
ardp_rqfree(rq);
rq = nxt;
}
}
/*
* ardp_set_retry - change default values for timeout
*
* ardp_set_retry takes a value for timout in seconds and a count
* of the number of retries to allow. It sets static variables in this
* file used by pralloc to set the default values in request structures
* it allocates.
*/
int
ardp_set_retry(int to, int rt)
{
/* XXX This is a critical section, but it is safe as long as we are not on
a multiprocessor and don't block. So no mutexes. */
ardp_default_timeout = to;
ardp_default_retry = rt;
/*** XXX End Critical section */
return(ARDP_SUCCESS);
}
#ifndef NDEBUG
/* Return 1 if the RREQ rr is a member of the list LIST. */
static int
rreq_member_of_list(RREQ rr, RREQ list)
{
for ( ; list; list = list->next) {
if (rr == list) return 1;
}
return 0; /* false */
}
#endif

View File

@@ -0,0 +1,305 @@
/*
* Copyright (c) 1991-1993 by the University of Southern California
*
* Written by bcn 1989-92 as dirsend.c in the Prospero distribution
* Modified by bcn 1/93 separate library and add support for asynchrony
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h>
#define OLD_GETHOSTBYNAME /* do it the old way, since we're on the client
*/
#ifdef PROSPERO
#include <pcompat.h>
#else /* not PROSPERO */
#define DISABLE_PFS_START()
#define DISABLE_PFS_END()
#endif /* not PROSPERO */
RREQ ardp_activeQ = NOREQ; /* Info about active requests */
RREQ ardp_completeQ = NOREQ;/* Completed requests */
static unsigned short ardp_def_port_no = 0; /* Default UDP port to use */
int ardp_port = -1; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
static ardp_init();
static short ardp_next_cid();
/*
* ardp_send - send a request and possibly wait for response
*
* ardp_send takes a pointer to a structure of type RREQ, an optional
* hostname, an optional pointer to the desination address, and the time to
* wait before returning in microseconds.
*
* If a destination address was specified, the address is inserted
* into the RREQ structure. If not, but a hostname was specified, the
* hostname is resolved, and its address inserted into the RREQ
* structure. The hostname may be followed by a port number in
* parentheses in which case the port field is filled in. If not
* specified, the Prospero directory server port is used as the default.
* If the host address is a non-null pointer to an empty address, then
* the address is also filled in.
*
* ardp_send then sends the packets specified by the request structure
* to the address in the request structure. If the time to wait is
* -1, it waits until the complete response has been received and
* returns PSUCCESS or PFAILURE depending on the outcome. Any
* returned packets are left in the RREQ strucure. If the time to
* wait is 0, ardp_send returns immediately. The prereq strucure will
* be filled in as the response is received if calls are made to
* ardp_check_messages (which may be called by an interrupt, or
* explicitly at appropriate points in the application. If the time
* to wait is positive, then ardp_send waits the specified lenght of
* time before returning.
*
* If ardp_send returns before the complete response has been
* received, it returns ARDP_PENDING (-1). This means that only
* the status field in the RREQ structure may be used until the status
* field indicates ARDP_STATUS_COMPLETE. In no event shall it be legal
* for the application to modify fields in the RREQ structure while a
* request is pending. If the request completes during the call to
* ardp_send, it returns ARDP_SUCCESS (0). On error, a positive
* return or status value indicates the error that occured.
*
* In attempting to obtain the response, the ARDP library will wait
* for a response and retry an appropriate number of times as defined
* by timeout and retries (both static variables). It will collect
* however many packets form the reply, and return them in the
* request structue.
*
* ARGS: req Request structure holding packets to send
* and to receive the response
* hname Hostname including optional port in parentheses
* dest Pointer to destination address
* ttwait Time to wait in microseconds
*
* MODIFIES: dest If pointer to empty address
* req Fills in ->recv and frees ->trns
*
* NOTE: In preparing packets for transmission, the packets
* are modified. Once the full response has been received,
* the packets that were sent are freed.
*/
int
ardp_send(RREQ req, /* Request structure to use (in, out) */
char *dname, /* Hostname (and port) of destination */
struct sockaddr_in *dest, /* Pointer to destination address */
int ttwait) /* Time to wait in microseconds */
{
char hostnoport[400];/* Hostname without port */
char *openparen; /* Start of port in dname */
int req_udp_port; /* UDP port from hostname */
#ifdef OLD_GETHOSTBYNAME /* unused */
struct hostent *host; /* Host info from gethostbyname */
#endif
PTEXT ptmp; /* Temporary packet pointer */
int DpfStmp; /* Used when disabling prospero */
int tmp; /* To temporarily hold return values */
p_clear_errors();
if((ardp_port < 0) && (tmp = ardp_init())) return(tmp);
if(req->status == ARDP_STATUS_FREE) {
fprintf(stderr,"Attempt to send free RREQ\n");
abort();
return(perrno = ARDP_BAD_REQ);
}
while(req->outpkt) {
req->outpkt->seq = ++(req->trns_tot);
ptmp = req->outpkt;
EXTRACT_ITEM(ptmp,req->outpkt);
APPEND_ITEM(ptmp,req->trns);
}
if(pfs_debug >= 9) {
fprintf(stderr, "In ardp_send - sending to %s\n", dname);
ptmp = req->trns;
while(ptmp) {
fprintf(stderr,"Packet %d:\n",ptmp->seq);
ardp_showbuf(ptmp->text, ptmp->length, stderr);
putc('\n', stderr);
ptmp = ptmp->next;
}
}
/* Assign connection ID */
req->cid = ardp_next_cid();
/* Resolve the host name, address, and port arguments */
/* If we were given the host address, then use it. Otherwise */
/* lookup the hostname. If we were passed a host address of */
/* 0, we must lookup the host name, then replace the old value */
if(!dest || (dest->sin_addr.s_addr == 0)) {
/* I we have a null host name, return an error */
if((dname == NULL) || (*dname == '\0')) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp_send: Null hostname specified\n");
return(perrno = ARDP_BAD_HOSTNAME);
}
/* If a port is included, save it away */
if(openparen = strchr(dname,'(')) {
sscanf(openparen+1,"%d",&req_udp_port);
if(req_udp_port) req->peer_port = htons(req_udp_port);
strncpy(hostnoport,dname,399);
if((openparen - dname) < 400) {
*(hostnoport + (openparen - dname)) = '\0';
dname = hostnoport;
}
}
#ifdef OLD_GETHOSTBYNAME
DISABLE_PFS_START();
assert(P_IS_THIS_THREAD_MASTER());
if((host = gethostbyname(dname)) == NULL) {
DISABLE_PFS_END();
/* Check if a numeric address */
req->peer.sin_family = AF_INET;
req->peer_addr.s_addr = inet_addr(dname);
if(req->peer_addr.s_addr == -1) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp: Can't resolve host %s\n", dname);
return(perrno = ARDP_BAD_HOSTNAME);
}
}
else {
DISABLE_PFS_END();
req->peer.sin_family = host->h_addrtype;
bcopy(host->h_addr, (char *)&(req->peer_addr),
host->h_length);
}
#else
/* New way of doing things */
if (ardp_hostname2addr(dname, &req->peer_addr))
return perrno = ARDP_BAD_HOSTNAME;
#endif
}
else bcopy(dest, &(req->peer), S_AD_SZ);
/* If no port set, use default port */
if(req->peer_port == 0) req->peer_port = ardp_def_port_no;
/* If dest was set, but zero, fill it in */
if(dest && (dest->sin_addr.s_addr == 0))
bcopy(&(req->peer), dest, S_AD_SZ);
if(tmp = ardp_headers(req)) return(tmp);
req->status = ARDP_STATUS_ACTIVE;
APPEND_ITEM(req,ardp_activeQ);
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
ardp_xmit(req, req->pwindow_sz);
return(ardp_retrieve(req,ttwait));
}
/*
* ardp_init - Open socket and bind port for network operations
*
* ardp_init attempts to determine the default destination port.
* It then opens a socket for network operations and attempts
* to bind it to an available privleged port. It tries to bind to a
* privileged port so that its peer can tell it is communicating with
* a "trusted" program. If it can not bind a priveleged port, then
* it also returns successfully since the system will automatically
* assign a non-priveleged port later, in which case the peer will
* assume that it is communicating with a non-trusted program. It
* is expected that in the normal case, we will fail to bind the
* port since most applications calling this routine should NOT
* be setuid.
*/
static int
ardp_init()
{
struct servent *sp; /* Entry from services file */
struct sockaddr_in us; /* Our address */
int DpfStmp;/* Used when disabling prospero */
int tmp; /* For stepping through ports */
/* Determine default udp port to use */
DISABLE_PFS_START();
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: getservbyname MT-Unsafe */
if ((sp = getservbyname(ARDP_DEFAULT_PEER,"udp")) == 0) {
if (pfs_debug >= 10)
fprintf(stderr, "ardp: udp/%s unknown service - using %d\n",
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
ardp_def_port_no = htons((u_short) ARDP_DEFAULT_PORT);
}
else ardp_def_port_no = sp->s_port;
DISABLE_PFS_END();
if (pfs_debug >= 10)
fprintf(stderr,"default udp port is %d\n", ntohs(ardp_def_port_no));
/* Open the local socket from which packets will be sent */
errno=0;
if((ardp_port = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
if (pfs_debug >= 1)
fprintf(stderr,"ardp: Can't open socket - %s\n",
unixerrstr());
return(perrno = ARDP_UDP_CANT);
}
#ifndef ARDP_NONPRIVED
/* Try to bind it to a privileged port - loop through candidate */
/* ports trying to bind. If failed, that's OK, we will let the */
/* system assign a non-privileged port later */
bzero((char *)&us, sizeof(us));
us.sin_family = AF_INET;
for(tmp = ARDP_FIRST_PRIVP; tmp < ARDP_FIRST_PRIVP+ARDP_NUM_PRIVP;tmp++) {
us.sin_port = htons((u_short) tmp);
if(bind(ardp_port, (struct sockaddr *)&us, sizeof(us)) == 0)
return(ARDP_SUCCESS);
if(errno != EADDRINUSE) return(ARDP_SUCCESS);
}
#endif /* ARDP_NONPRIVED */
return(ARDP_SUCCESS);
}
/*
* ardp_next_cid - return next connection ID in network byte order
*
* ardp_next_cid returns the next connection ID to be used
* after first converting it to network byte order.
*/
static short ardp_next_cid()
{
static unsigned short next_conn_id = 0; /* Next conn id to use */
static int last_pid = 0; /* Reset after forks */
int pid = getpid();
/* If we did a fork, reinitialize */
if(last_pid != pid) {
if(ardp_port >= 0) close(ardp_port);
ardp_port = -1;
next_conn_id = 0;
ardp_init();
}
/* Find first connection ID */
assert(P_IS_THIS_THREAD_MASTER()); /* rand and srand are unsafe */
if(next_conn_id == 0) {
srand(pid+time(0));
next_conn_id = rand();
last_pid = pid;
}
if(++next_conn_id == 0) ++next_conn_id;
return(htons(next_conn_id));
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1993 by the University of Southern Calfornia
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <stdio.h>
#include <ctype.h>
static void showc(char c, FILE *outf);
/* Return non-zero if string ends in a newline. */
/* Like fputs, but for bstrings. */
void
ardp_showbuf(const char *bst, int len, FILE *out)
{
while (len-- > 0) {
showc(*bst++, out);
}
}
#include <ctype.h>
extern int pfs_debug;
static void
showc(char c, FILE *outf)
{
if (c == '\\') {
putc('\\', outf);
putc('\\', outf);
} else if (isprint(c)) {
putc(c, outf);
} else if ((c == '\n')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('n', outf);
} else {
putc('\n', outf);
}
} else if ((c == '\t')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('t', outf);
} else {
putc('\t', outf);
}
} else if ((c == '\r')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('r', outf);
} else {
putc('\r', outf);
}
} else {
fprintf(outf, "\\%#03o", c);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to send a single packet to a peer
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <plog.h>
#include <errno.h>
#include <perrno.h>
extern int ardp_srvport;
extern int ardp_prvport;
/*
* ardp_snd_pkt - transmits a single packet to address in req
*
* ardp_snd_pkt takes a pointer to a packet of type PTEXT to be
* sent to a peer identified by req->peer. It then send the packet to
* the peer. If the packet was sent successfully, ARDP_SUCCESS is
* returned. Successful transmission of the packet does not provide
* any assurance of receipt by the peer. If the attempt to send
* the packet fails, ARDP_NOT_SENT is returned.
*/
int
ardp_snd_pkt(pkt,req)
PTEXT pkt;
RREQ req;
{
int sent;
sent = sendto(((ardp_prvport != -1) ? ardp_prvport : ardp_srvport),
pkt->start, pkt->length, 0, &(req->peer), S_AD_SZ);
if(sent == pkt->length) return(ARDP_SUCCESS);
plog(L_NET_ERR, req, "Attempt to send message failed (errno %d %s)",
errno, unixerrstr(), 0);
return(ARDP_NOT_SENT);
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1991 as part of rdgram.c in Prospero distribution
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <ardp.h>
#include <plog.h>
int (*ardp_pri_func)() = NULL; /* Function to compare priorities */
int ardp_pri_override = 0; /* If 1, then oveeride value in request */
int ardp_srvport = -1;
int ardp_prvport = -1;
/*
* ardp_set_queueing_plicy - set function for queueing policy
*
* ardp_set_queuing_policy allows one to provide a function that will set
* priorities for requests. When passed two req structures, r1 and r2, the
* function should return a negative number if r1 should be executed first
* (i.e. r1 has a lower numerical priority) and positive if r2 should be
* executed first. If the function returns 0, it means the two have the
* same priority and should be executed FCFS. If override is non-zero, then
* the priority function is to be applied to all requests. If non-zero,
* it is only applied to those with identical a priori priorities (as
* specified in the datagram itself.
*/
int
ardp_set_queuing_policy(pf,override)
int (*pf)(); /* Function to compare priorities */
int override; /* If 1, then oveeride value in request */
{
ardp_pri_func = pf;
ardp_pri_override = override;
return(ARDP_SUCCESS);
}
int
ardp_set_prvport(port)
int port;
{
ardp_prvport = port;
return(ARDP_SUCCESS);
}
int
ardp_bind_port(portname)
char *portname;
{
struct sockaddr_in s_in = {AF_INET};
struct servent *sp;
int on = 1;
int port_no = 0;
assert(P_IS_THIS_THREAD_MASTER()); /*getpwuid MT-Unsafe*/
if(*portname == '#') {
sscanf(portname+1,"%d",&port_no);
if(port_no == 0) {
fprintf(stderr, "ardp_bind_port: port number must follow #\n");
exit(1);
}
s_in.sin_port = htons((ushort) port_no);
}
else if((sp = getservbyname(portname, "udp")) != NULL) {
s_in.sin_port = sp->s_port;
}
else if(strcmp(portname,ARDP_DEFAULT_PEER) == 0) {
fprintf(stderr, "ardp_bind_port: udp/%s unknown service - using %d\n",
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
s_in.sin_port = htons((ushort) ARDP_DEFAULT_PORT);
}
else {
fprintf(stderr, "ardp_bind_port: udp/%s unknown service\n",portname);
exit(1);
}
if ((ardp_srvport = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
plog(L_STATUS,NOREQ,"Startup - Can't open socket",0);
fprintf(stderr, "ardp_bind_port: Can't open socket\n");
exit(1);
}
if (setsockopt(ardp_srvport, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
fprintf(stderr, "dirsrv: setsockopt (SO_REUSEADDR)\n");
if (bind(ardp_srvport, (struct sockaddr *) &s_in, S_AD_SZ) < 0) {
plog(L_STATUS,NOREQ,"Startup - Can't bind socket",0);
fprintf(stderr, "dirsrv: Can not bind socket\n");
exit(1);
}
return(ntohs(s_in.sin_port));
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 1/93 to send a list of packets to a destination
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() and select() */
extern int pfs_debug; /* Debug level */
extern int ardp_port; /* Opened UDP port */
/*
* ardp_xmit - transmits packets in req->trns
*
* ardp_xmit takes a pointer to a request structure of type RREQ and a
* window size. It then sends the packet on the request structure
* transmit queue to the peer address in the request structure starting after
* the indicated peer rcvd_thru value, and up to the number of packets
* specified by the window size. It returns ARDP_SUCCESS on success and
* returns an error code on failure.
*
* This is called on both the client and server side, called respectively by
* ardp_send() and ardp_pr_actv().
*/
int
ardp_xmit(RREQ req, /* Request structure with packets to send */
int window) /* Max packets to send at once. Note that
right now this is always identical to
req->pwindow_sz.
0 means infinite window size
-1 means just send an ACK; don't send any
data packets. */
{
PTEXT ptmp; /* Packet pointer for stepping through trns */
unsigned short stmp; /* Temp short for conversions */
int ns; /* Number of bytes actually sent */
static PTEXT ack = NOPKT; /* Only an ack to be sent */
if(window < 0 || req->prcvd_thru >= req->trns_tot) {
/* All our packets got through, send acks only */
if(ack == NOPKT) {
ack = ardp_ptalloc();
/* Add header */
ack->start -= 9;
ack->length += 9;
*(ack->start) = (char) 9;
/* An unsequenced control packet */
bzero4(ack->start+3);
}
/* Received Through */
stmp = htons(req->rcvd_thru);
bcopy2(&stmp,ack->start+7);
/* Connection ID */
bcopy2(&(req->cid),ack->start+1);
ptmp = ack;
}
else ptmp = req->trns;
/* Note that we don't want to get rid of packts before the */
/* peer received through since the peer might later tell */
/* us it forgot them and ask us to send them again */
/* XXX whether this is allowable should be an application */
/* specific configration option. */
while(ptmp) {
if((window > 0) && (ptmp->seq > req->prcvd_thru + window)) break;
if((ptmp->seq == 0) || (ptmp->seq > req->prcvd_thru)) {
if (pfs_debug >= 6) {
if (req->peer.sin_family == AF_INET)
fprintf(stderr,
"Sending message%s (cid=%d) (seq=%d) to %s(%d)...",
(ptmp == ack) ? " (ACK only)" : "",
ntohs(req->cid), ntohs(ptmp->seq),
inet_ntoa(req->peer_addr), PEER_PORT(req));
else fprintf(stderr,"Sending message...");
(void) fflush(stderr);
}
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
&(req->peer), S_AD_SZ);
if(ns != ptmp->length) {
if (pfs_debug >= 1) {
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
perror("");
}
return(ARDP_NOT_SENT);
}
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
}
ptmp = ptmp->next;
}
return(ARDP_SUCCESS);
}

View File

View File

@@ -0,0 +1,72 @@
/* Copyright (c) 1993, by Pandora Systems */
/* Author: Mitra <mitra@path.net> */
/* Allocation code copied and adapted from:
prospero/alpha.5.2a+/lib/pfs/flalloc */
#include "dnscache_alloc.h"
#include <pfs.h>
#include <pfs_threads.h>
#include <mitra_macros.h>
static DNSCACHE lfree = NULL; /* Free dnscaches */
/* These are global variables which will be read by dirsrv.c
Too bad C doesn't have better methods for structuring such global data. */
int dnscache_count = 0;
int dnscache_max = 0;
/************* Standard routines to alloc, free and copy *************/
/*
* dnscache_alloc - allocate and initialize DNSCACHE structure
*
* returns a pointer to an initialized structure of type
* DNSCACHE. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
DNSCACHE
dnscache_alloc()
{
DNSCACHE acache;
TH_STRUC_ALLOC(dnscache,DNSCACHE,acache);
acache->name = NULL;
acache->usecount = 0;
bzero(&acache->sockad,sizeof(acache->sockad));
return(acache);
}
/*
* dnscache_free - free a DNSCACHE structure
*
* dnscache_free takes a pointer to a DNSCACHE structure and adds it to
* the free list for later reuse.
*/
void
dnscache_free(DNSCACHE acache)
{
stfree(acache->name) ; acache->name = NULL;
TH_STRUC_FREE(dnscache,DNSCACHE,acache);
}
/*
* dnscache_lfree - free a linked list of DNSCACHE structures.
*
* dnscache_lfree takes a pointer to a dnscache structure frees it and
* any linked
* DNSCACHE structures. It is used to free an entire list of WAISMSGBUFF
* structures.
*/
void
dnscache_lfree(acache)
DNSCACHE acache;
{
TH_STRUC_LFREE(DNSCACHE,acache,dnscache_free);
}
void
dnscache_freespares()
{
TH_FREESPARES(dnscache,DNSCACHE);
}

View File

@@ -0,0 +1,33 @@
#ifndef dnscache_alloc_h
#define dnscache_alloc_h
#include <pfs.h>
#include <pfs_threads.h>
#include <netinet/in.h>
struct dnscache {
#ifdef ALLOCATOR_CONSISTENCY_CHECK
int consistency;
#endif
char *name;
struct sockaddr_in sockad;
int usecount; /* For determining size of cache */
struct dnscache *next;
struct dnscache *previous;
};
typedef struct dnscache *DNSCACHE;
typedef struct dnscache DNSCACHE_ST;
extern DNSCACHE dnscache_alloc();
extern void dnscache_free(DNSCACHE acache);
extern void dnscache_lfree(DNSCACHE acache);
extern void dnscache_freespares();
extern int dnscache_count, dnscache_max;
/*extern DNSCACHE dnscache_copy(DNSCACHE f, int r);*/
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexDNSCACHE;
extern p_th_mutex p_th_mutexALLDNSCACHE;
#endif
#endif /*dnscache_alloc_h*/

221
prospero/lib/ardp/flocks.c Normal file
View File

@@ -0,0 +1,221 @@
/* Copyright (c) 1993, by Pandora Systems */
/* Author: Mitra <mitra@path.net> */
/* Allocation code copied and adapted from:
lib/pfs/flalloc.c in the Prospero Alpha.5.2a release. */
#include <pfs.h>
#include <plog.h>
#include "flocks.h"
#include "mitra_macros.h"
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexFILES;
#endif
/* FileLocks are currently unused by dirsrv.c, and not linked into the ardp
library. So dirsrv will not report on them in replies to a STATUS message.
*/
static FILELOCK lfree = NULL; /* Free filelocks */
/* These are global variables which will be read by dirsrv.c
Too bad C doesn't have better methods for structuring such global data. */
int filelock_count = 0;
int filelock_max = 0;
int filelock_open = 0;
int filelock_open_max = 0;
int filelock_sepwaits = 0;
int filelock_secwaits = 0;
FILELOCK filelock_locked = NULL;
/************* Standard routines to alloc, free and copy *************/
/*
* filelock_alloc - allocate and initialize FILELOCK structure
*
* returns a pointer to an initialized structure of type
* FILELOCK. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
FILELOCK
filelock_alloc()
{
FILELOCK fl;
TH_STRUC_ALLOC(filelock,FILELOCK,fl);
fl->name = NULL;
fl->readers = 0;
return(fl);
}
/*
* filelock_free - free a FILELOCK structure
*
* filelock_free takes a pointer to a FILELOCK structure and adds it to
* the free list for later reuse.
*/
void
filelock_free(FILELOCK fl)
{
stfree(fl->name); fl->name = NULL;
fl->readers = 0;
TH_STRUC_FREE(filelock, FILELOCK, fl);
}
/*
* filelock_lfree - free a linked list of FILELOCK structures.
*
* filelock_lfree takes a pointer to a filelock structure frees it and
* any linked
* FILELOCK structures. It is used to free an entire list of FILELOCK
* structures.
*/
void
filelock_lfree(fl)
FILELOCK fl;
{
TH_STRUC_LFREE(FILELOCK,fl,filelock_free);
}
static void
filelock_unreaders(FILELOCK flock)
{
/* Assumes p_th_mutexFILES is locked already */
assert(flock->readers > 0);
if (!(--flock->readers)) {
EXTRACT_ITEM(flock,filelock_locked);
filelock_free(flock);
}
}
static void
filelock_unwriters(FILELOCK flock)
{
/* Assumes p_th_mutexFILES is locked already */
assert(flock->readers == -1);
EXTRACT_ITEM(flock, filelock_locked);
filelock_free(flock);
}
void
filelock_freespares()
/* This is used for filelocks to free up space in the child */
{
TH_FREESPARES(filelock,FILELOCK);
}
void
filelock_release(const char *filename, int readonly)
{
FILELOCK flock;
p_th_mutex_lock(p_th_mutexFILES);
flock = filelock_locked;
FIND_FNCTN_LIST(flock, name, filename, stequal);
assert(flock); /* it better be locked */
if (readonly) {
filelock_unreaders(flock); /* May destroy flock */
} else {
filelock_unwriters(flock); /* May destroy flock */
}
filelock_open--;
p_th_mutex_unlock(p_th_mutexFILES);
}
int
locked_fclose_A(FILE *afile, const char *filename, int readonly)
{
int retval;
/* Assumes already obtained filelock for filename */
retval = fclose(afile);
/* At least on solaris, this can return an error for no apparent reason */
#if 0
assert(!retval);
#endif
filelock_release(filename, readonly);
return(retval);
}
void
filelock_obtain(const char *filename, int readonly)
{
FILELOCK(flock);
int haswaited = 0;
for (;;) {
p_th_mutex_lock(p_th_mutexFILES);
flock = filelock_locked;
FIND_FNCTN_LIST(flock, name, filename,stequal);
if (!flock) { /* didnt find a matching lock */
flock = filelock_alloc();
flock->name = stcopy(filename);
flock->readers = 0;
APPEND_ITEM(flock,filelock_locked);
}
/* Found, or created a matching lock */
if (readonly) {
if (flock->readers >= 0) {
flock->readers++;
break;
}
/* Drops thru here, if we want it readonly, but someone else writing*/
} else {
if (flock->readers == 0) {
flock->readers = -1; /* Special code for writer */
break;
}
/* Drops thru here, if we want to write, but someone else
is reading/writing */
}
/* At this point we cant lock it, so unlock mutex, wait, and try again*/
p_th_mutex_unlock(p_th_mutexFILES);
plog(L_QUEUE_INFO,NOREQ, "Waiting for filelock for %s", filename, 0);
if (!haswaited) filelock_sepwaits++;
filelock_secwaits++;
sleep(1); /* Maybe too long */
} /*for*/
if (++filelock_open > filelock_open_max) {
filelock_open_max = filelock_open;
}
/* break is always done with mutex locked */
p_th_mutex_unlock(p_th_mutexFILES);
}
FILE *
locked_fopen(const char *filename, const char *mode)
{
FILELOCK flock;
FILE *retval;
int readonly = stequal(mode,"r");
filelock_obtain(filename,readonly); /* Will wait till available */
if (!(retval = fopen(filename,mode))) {
filelock_release(filename, readonly);
}
return retval;
}
/* Suuitable sequence for creating a file via a temporary
filelock_obtain(filename,FALSE);
if (!(afile = locked_fopen(tmpfilename, "w")) )
filelock_release(filename,FALSE);
written stuff to the file - retval set if fails
return(locked_fclose_and_rename(afile, tmpfilename, filenam,retvale));
*/
int
locked_fclose_and_rename(
FILE *afile, /* Open "w" temporary file */
const char *tmpfilename, /* Name of temp file */
const char *filename, /* Name desired */
int retval) /* FALSE if ok to rename, TRUE cleanup*/
{
if (fflush(afile) || ferror(afile)) { retval = PFAILURE; }
if (locked_fclose_A(afile, tmpfilename, FALSE)) { retval = PFAILURE; }
if (!retval) { /* Dont attempt to rename if failed */
if (rename(tmpfilename, filename)) { retval = PFAILURE; }
}
unlink(tmpfilename);
filelock_release(filename,FALSE);
return(retval);
}

View File

@@ -0,0 +1,28 @@
#ifndef rmg_filelock_h
#define rmg_filelock_h
#include <pfs.h>
struct filelock {
#ifdef ALLOCATOR_CONSISTENCY_CHECK
int consistency;
#endif
char *name;
int readers; /* -1 for writing */
/* Note we dont keep the fileno here since each locker opens seperately*/
struct filelock *next;
struct filelock *previous;
};
typedef struct filelock *FILELOCK;
typedef struct filelock FILELOCK_ST;
extern FILELOCK filelock_alloc();
extern void filelock_free(FILELOCK chan);
extern void filelock_lfree(FILELOCK chan);
extern void filelock_freespares();
extern FILELOCK filelock_copy(FILELOCK f, int r);
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexFILELOCK;
#endif
#endif /*rmg_filelock_h*/

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <ardp.h>
#include <perrno.h>
#include <sys/types.h> /* for gethostbyname() */
#include <sys/socket.h> /* for gethostbyname */
#include <netdb.h> /* for gethostbyname. */
#include <netinet/in.h> /* for struct sockaddr_in */
#include <pmachine.h> /* for bzero */
#include <string_with_strcasecmp.h> /* for strcasecmp */
#ifdef PROSPERO
#include <pserver.h> /* For DNSCACHE_MAX */
#ifdef DNSCACHE_MAX
#include "dnscache_alloc.h"
#endif
#include <pcompat.h>
#else /* not PROSPERO */
#define DISABLE_PFS_START()
#define DISABLE_PFS_END()
#endif /* not PROSPERO */
extern int stcaseequal(const char *s1,const char *s2);
/*
* This function serves as a thread-safe version of gethostbyname(),
* which is not a re-entrant function since it uses static data.
*
* It normally accepts a hostname and initializes the socket address
* appropriately, then returns PSUCCESS. Also accepts numeric addresses.
* Does not currently handle the port #, although that would be a useful future
* extension.
*
* It returns ARDP_BAD_HOSTNAME if the hostname could not be resolved.
* gethostbyname should not be called anywhere else in multi-threaded versions
* of the Prospero code; to this end, an error define occurs for it in
* pfs_threads.h
*
* Oh no there isn't a definition in pfs_threads.h - Mitra
*
* Note that gethostbyname() is not multi-threaded internally, and
* does block, so we might block on name resolution as a bottleneck.
* Probably want a multithreaded name resolver library. Release such a thing
* as freeware?
*
* It also converts numeric addresses appropriately.
*/
/* If change this - uncomment/comment initialization in server/dirsrv.c */
#ifdef DNSCACHE_MAX
#include "dnscache_alloc.h"
#include <mitra_macros.h> /* FIND_FNCTN_LIST */
#include <string.h> /* For strcmp */
DNSCACHE alldnscaches = NULL;
int alldnscache_count = 0;
void
sockaddr_copy(struct sockaddr_in *src, struct sockaddr_in *destn)
{
/* Nothing in a sockaddr_in is a pointer */
memcpy(destn, src, sizeof(struct sockaddr_in));
}
#endif /*DNSCACHE_MAX*/
/* Caching has been added, to this - take care that it does what you
want, I'm certainly open to changes if this isnt what we need.
Currently it is called by something at a higher layer, with a
hostname of the name to cache, and a hostaddr of NULL.
Currently this is used to cache all the hostnames hard coded
into include/* on the assumption that these are unlikely to move around
while a server is running. Later, we may want to delete a cached
entry periodically, or if it fails.
The first thing in alldnscaches is always a copy of the last thing
found, to allow really quick returns on repeat requests.
Note - great care is taken here to
a) avoid deadlock between GETHOSTBYNAME and DNSCACHE mutexes
b) avoid requirement for GETHOSTBYNAME mutex, if found in cache
This allows multiple cached results to be returned while a
single thread calls gethostbyname
*/
void
ardp_hostname2addr_initcache()
{
}
static void
dnscache_clean()
{
DNSCACHE dc, nextdc;
if (alldnscache_count > DNSCACHE_MAX) {
if (! p_th_mutex_trylock(p_th_mutexALLDNSCACHE)) {
/* Since this is only optimisation, skip if its locked already */
for (dc = alldnscaches; dc ; dc = nextdc) {
nextdc = dc->next;
if (!(--dc->usecount)) {
EXTRACT_ITEM(dc,alldnscaches);
dnscache_free(dc);
alldnscache_count--;
}
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
}
}
}
int
ardp_hostname2addr(const char *hostname, struct sockaddr_in *hostaddr)
{
struct hostent *hp; /* Remote host we're connecting to. */
int retval; /* Value to return */
#define RETURN(rv) { retval = (rv); goto cleanup; }
#ifdef PROSPERO
int DpfStmp; /* for DISABLE_PFS_START() */
#endif
#ifdef DNSCACHE_MAX
DNSCACHE acache = NULL;
acache = alldnscaches;
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
/* Cant use TH_FIND_FNCTN_LIST because must retain lock */
FIND_FNCTN_LIST(acache, name, hostname, stcaseequal);
if(acache) {
acache->usecount++;
if (hostaddr) {
/* Note is is pointless, but not harmfull to call again
for same hostaddr - may just want to rerun*/
sockaddr_copy(&(acache->sockad),hostaddr);
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Also released below*/
return(ARDP_SUCCESS); /* Dont free acache */
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Note also released above*/
acache = dnscache_alloc(); /*locks DNSCACHE temporarily*/
acache->name = stcopy(hostname);
if (!hostaddr) { hostaddr = &(acache->sockad); }
#endif /*DNSCACHE_MAX*/
DISABLE_PFS_START(); /* Turn off compatibility library if on */
p_th_mutex_lock(p_th_mutexGETHOSTBYNAME);
hp = gethostbyname((char *) hostname); /* cast to char * in case bad prototype.
*/
DISABLE_PFS_END(); /* Restore compat. lib. */
if (hp == NULL) {
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME);
/* Try to see if it might be a numeric address. */
/* Check if a numeric address */
hostaddr->sin_family = AF_INET;
hostaddr->sin_addr.s_addr = inet_addr(hostname);
if(hostaddr->sin_addr.s_addr == -1) {
p_clear_errors(); /* clear p_err_string if set. */
RETURN(perrno = ARDP_BAD_HOSTNAME);
}
RETURN(ARDP_SUCCESS);
}
bzero((char *) hostaddr, sizeof *hostaddr);
memcpy((char *)&hostaddr->sin_addr, hp->h_addr, hp->h_length);
hostaddr->sin_family = hp->h_addrtype;
/* Don't unlock the mutex until we're no longer reading from hp. */
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME); /* Note can be unlocked above*/
/* Copy last result into cache */
#ifdef DNSCACHE_MAX
if (alldnscaches == NULL)
ardp_hostname2addr_initcache();
sockaddr_copy(hostaddr,&(acache->sockad));
/* Boost initially, to bias towards keeping recent*/
acache->usecount = 5;
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
APPEND_ITEM(acache,alldnscaches);
alldnscache_count++;
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
dnscache_clean(); /* Only does anything if cache too big */
#endif /*DNSCACHE_MAX*/
return(ARDP_SUCCESS); /* Dont free acache */
cleanup:
#ifdef DNSCACHE_MAX
if (acache) dnscache_free(acache);
#endif
return(retval);
}
/* Prototype needs to go into here, not just in pfs.h. */
int
stcaseequal(const char *s1,const char *s2)
{
if (s1 == s2) /* test for case when both NULL*/
return TRUE;
if (!s1 || !s2) /* test for one NULL */
return FALSE;
return (strcasecmp(s1, s2) == 0);
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs_threads.h>
#include <ardp.h> /* for internal error stuff. */
/* This is the only section of code which calls the pthread_ routines directly.
Everything else is through the interface in pfs_threads.h. */
#ifdef PFS_THREADS
/* Don't compile this if !PFS_THREADS, because it overrides macro definitions
*/
static struct {
p_th_t thread;
int inuse;
} thread_map[P_MAX_NUM_THREADS];
#ifdef PFS_THREADS_SOLARIS
thread_key_t thread_map_key;
#endif
int
p__th_self_num(void)
{
#if defined(PFS_THREADS_FLORIDA) || !defined(NDEBUG)
p_th_t self = p_th_self();
#endif
#ifdef PFS_THREADS_FLORIDA
int i;
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
if (thread_map[i].inuse
&& p_th_equal(thread_map[i].thread, self))
return i;
}
#endif
#ifdef PFS_THREADS_SOLARIS
long val;
if (!thread_map_key) return 0; /* Assume not threading */
if (!thr_getspecific(thread_map_key,(void *)&val)) {
assert(p_th_equal(thread_map[val].thread, self));
assert(val < P_MAX_NUM_THREADS); /* i.e. 0 .. MAX-1 */
return val;
}
#endif /*PFS_THREADS_SOLARIS*/
internal_error("p__th_self_num() called for a thread that didn't have its \
number set with p__th_allocate_self_num() or p__th_set_self_master()");
return -1 ; /* Keep Gcc happy */
}
void
p__th_set_self_master(void)
{
assert(!thread_map[0].inuse);
thread_map[0].inuse = 1;
thread_map[0].thread = p_th_self();
#ifdef PFS_THREADS_SOLARIS
assert(!thread_map_key);
thr_keycreate(&thread_map_key, NULL);
thr_setspecific(thread_map_key, 0);
#endif
}
/*
* This allocates a number to this thread.
* It also does consistency checking to make sure the function is called
* only on a thread that doesn't have a number already allocated.
*/
void
p_th_allocate_self_num(void)
{
int allocated = 0;
p_th_t self = p_th_self();
int i;
CHECK_MEM();
assert(thread_map_key); /* Better be initialized*/
/* I think this needs mutexing */
p_th_mutex_lock(p_th_mutexARDP_SELFNUM);
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
if (!thread_map[i].inuse) {
if (!allocated) {
thread_map[i].thread = self;
thread_map[i].inuse = 1;
++allocated;
CHECK_MEM();
#ifdef PFS_THREADS_SOLARIS
thr_setspecific(thread_map_key,(void *)i);
#endif
}
} else {
if(p_th_equal(thread_map[i].thread, self)) {
internal_error("Shouldn't allocate a number to a thread twice.");
}
}
}
p_th_mutex_unlock(p_th_mutexARDP_SELFNUM);
}
void
p_th_deallocate_self_num(void)
{
int i = p__th_self_num();
thread_map[i].inuse = 0;
}
extern p_th_mutex p_th_mutexFILES;
#ifndef NDEBUG
char mutex_locked_msg[] = "Mutex %s locked\n";
#endif
#ifdef PFS_THREADS_SOLARIS
/* Return true if fails to lock - i.e was already locked */
int
p_th_mutex_islocked(mutex_t *mp)
{
int retval;
if (retval = mutex_trylock(mp)) {
return retval;
} else {
return mutex_unlock(mp);
}
}
#endif /* PFS_THREADS_SOLARIS */
#endif /*PFS_THREADS*/

View File

@@ -0,0 +1,324 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#if !defined(AIX) && !defined(SOLARIS)
#include <vfork.h>
#endif
#include <malloc.h>
#include <search.h>
#include <memory.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include "typedef.h"
#include "db_files.h"
#include "host_db.h"
#include "header.h"
#include "error.h"
#include "archie_strings.h"
#include "files.h"
#include "master.h"
#include "protos.h"
#include "db_ops.h"
/* This performs a simple ACL based on ip addresses */
typedef struct {
int ip[4]; /* Composes the ip address a.b.c.d */
} ip_t;
#define DIRSRV_ACL_FILE "dirsrv.acl"
#define DIRSRV_ACL_MESSAGE_FILE "dirsrv.acl.mesg"
#define DIRSRV_ACL_MESSAGE_DEFAULT "Access to this server is restricted"
static ip_t *acl_list = NULL;
static int acl_list_num = 0;
static int acl_list_max = 0;
static int acl_not_present = 0;
static char acl_err_mesg[100];
#define IP_STAR 257
extern int errno;
static int qcompare_ip(a,b)
ip_t *a, *b;
{
if ( a->ip[0] != b->ip[0] )
return a->ip[0]- b->ip[0];
if ( a->ip[1] != b->ip[1] )
return a->ip[1]- b->ip[1];
if ( a->ip[2] != b->ip[2] )
return a->ip[2]- b->ip[2];
return a->ip[3]- b->ip[3];
}
static int compare_ip(a,b) /* Assuming that can contain * */
ip_t *a, *b;
{
if ( b->ip[0] == IP_STAR )
return 0;
if ( a->ip[0] != b->ip[0] )
return a->ip[0]- b->ip[0];
if ( b->ip[1] == IP_STAR )
return 0;
if ( a->ip[1] != b->ip[1] )
return a->ip[1]- b->ip[1];
if ( b->ip[2] == IP_STAR )
return 0;
if ( a->ip[2] != b->ip[2] )
return a->ip[2]- b->ip[2];
if ( b->ip[3] == IP_STAR )
return 0;
return a->ip[3]- b->ip[3];
}
static int file_proc(ft,name,present)
file_info_t *ft;
char *name;
int *present;
{
struct stat st;
*present = 1;
if ( ft == NULL ) {
error(A_ERR,"file_proc", "Unable to create ft file pointer");
return 0;
}
sprintf(ft->filename,"%s/%s/%s",get_archie_home(),DEFAULT_ETC_DIR,name);
if ( stat(ft->filename,&st) == -1 ) {
if ( errno == ENOENT ) {
*present = 0;
return 0;
}
error(A_ERR,"file_proc","Error finding ft: %s, errno = %d",ft->filename,errno);
return 0;
}
if ( open_file(ft, O_RDONLY) == ERROR ) {
error(A_ERR,"file_proc", "Error opening acl file: %s",ft->filename);
return 0;
}
return 1;
}
static void read_acl_message()
{
char buff[100];
int i;
file_info_t *acl_mesg = create_finfo();
strcpy(acl_err_mesg, DIRSRV_ACL_MESSAGE_DEFAULT);
if ( file_proc(acl_mesg,DIRSRV_ACL_MESSAGE_FILE,&i) ) {
if ( fgets(buff,99,acl_mesg->fp_or_dbm.fp) != NULL ) {
*(strrchr(buff,'\n')) = '\0';
strcpy(acl_err_mesg,buff);
}
close_file(acl_mesg);
destroy_finfo(acl_mesg);
}
}
int read_acl_file()
{
char buff[100];
int i,j;
char **av;
file_info_t *acl_file = create_finfo();
if (! file_proc(acl_file,DIRSRV_ACL_FILE,&j) ) {
if ( j == 0 ) {
acl_not_present = 1;
destroy_finfo(acl_file);
return 1;
}
destroy_finfo(acl_file);
return 0;
}
/* Count the number of items */
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
i = 0;
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
i++;
}
if ( i == 0 ) {
error(A_INFO,"read_acl_file","ACL file is empty");
acl_not_present = 1;
destroy_finfo(acl_file);
return 1;
}
if ( acl_list_max == 0 ) { /* New */
acl_list_max = i+10;
acl_list = (ip_t*)malloc(sizeof(ip_t)*acl_list_max);
if ( acl_list == NULL ) {
error(A_ERR,"read_acl_file","Unable to allocate memory");
destroy_finfo(acl_file);
return 0;
}
}
else {
ip_t *tmp;
if ( acl_list_max <= i ) {
acl_list_max = i+10;
tmp = (ip_t*)realloc(acl_list, sizeof(ip_t)*acl_list_max);
if ( tmp == NULL ) {
error(A_ERR,"read_acl_file", "Unable to expand allocated memory");
}
acl_list = tmp;
}
}
acl_list_num = 0;
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
av = str_sep(buff,'.');
if ( av == NULL ) {
error(A_ERR,"read_acl_file", "Unable to decompose string: %s",buff);
}
for ( i = 0; i < 4; i++ ) {
if ( av[i] == NULL|| av[i][0] == '*' ) {
break;
}
acl_list[acl_list_num].ip[i] = atoi(av[i]);
}
for ( ; i < 4; i++ ) {
acl_list[acl_list_num].ip[i] = IP_STAR;
}
acl_list_num++;
}
close_file(acl_file);
qsort(acl_list,acl_list_num, sizeof(ip_t),qcompare_ip);
read_acl_message();
destroy_finfo(acl_file);
return 1;
}
int verify_acl_list(from)
struct sockaddr_in *from;
{
ip_t ip;
int i;
char **av;
char *ip_addr;
if ( acl_not_present )
return 1;
if ( acl_list == NULL ) {
if (!read_acl_file() )
return 0;
if ( acl_not_present )
return 1;
}
ip_addr = inet_ntoa(from->sin_addr);
printf("%s\n",ip_addr);
/* decompose address */
av = str_sep(ip_addr,'.');
if ( av == NULL ) {
error(A_ERR,"verify_acl_list","Unable to decompsoe ip address: %s. Accepting",ip_addr);
return 1;
}
ip.ip[0] = atoi(av[0]);
ip.ip[1] = atoi(av[1]);
ip.ip[2] = atoi(av[2]);
ip.ip[3] = atoi(av[3]);
if ( ip.ip[0] == 127 && ip.ip[1] == 0 && ip.ip[2] == 0 && ip.ip[3] == 1 ) {
free_opts(av);
return 1;
}
for ( i = 0; i < acl_list_num; i++ ) {
int ret;
ret = compare_ip(&ip, &acl_list[i]);
if ( ret == 0 ){
free_opts(av);
return 1;
}
if ( ret < 0 ) {
free_opts(av);
return 0;
}
}
free_opts(av);
return 0;
}
char *acl_message()
{
return acl_err_mesg;
}
#if 0
char *prog;
int main(argc,argv)
int argc;
char **argv;
{
char buff[100];
struct sockaddr_in from;
prog = argv[0];
while ( fgets(buff,99,stdin) != NULL ) {
*(strrchr(buff,'\n')) = '\0';
printf("Checking %s, ",buff);
from.sin_addr.s_addr = inet_addr(buff);
if ( verify_acl_list(&from) )
printf("Ok\n");
else
printf("No:%s\n",acl_message());
}
return 0;
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pmachine.h>
#if defined(HAVESTRERROR)
#include <errno.h>
#include <string.h> /* For stringerr*/
#else
#include <errno.h> /* For sys_nerr and sys_errlist*/
#ifndef SOLARIS
/* definitely needed under SunOS; probably under almost everything right
now. Solaris's <errno.h> declares these; others don't. */
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* ndef SOLARIS */
#undef HAVESTRERROR
#endif
const char *
unixerrstr(void)
{
#ifdef HAVESTRERROR
/* sys_errlist is not in SOLARIS, replace with strerror()
which may not be thread safe in some applications
there doesnt appear to be a posix compliant equivalent */
return strerror(errno);
#else
/* Would be nice to have the message include the error #. */
return errno < sys_nerr ? sys_errlist[errno] : "Unprintable Error";
#endif
}

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/* This string is modified in ardp_xmit.c. That forces the C compiler to
include it in the Prospero binaries. If you know a less kludgy way to
force a fancy optimizing C compiler to include it in the binaries, please
let us know.
*/
char *usc_license_string = "PROSPERO(TM) Copyright (c) 1991-1993 University of Southern California\nPROSPERO is a trademark of the University of Southern California\n";