fresh git tree for public release

we regretfully had to remove our git history for licensing reasons

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2010-10-11 14:59:26 -04:00
commit 0ad4db4fad
271 changed files with 71255 additions and 0 deletions

46
libtirpc/.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
# files generated by autoconf, automake, autoheader and libtoolize
aclocal.m4
autom4te.cache
compile
config.guess
config.log
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
Makefile.in
missing
config.h.in
# files generated by configure
confdefs.h
config.status
conftest
conftest.c
conftest.cpp
conftest.er1
conftest.err
.deps
Makefile
config.h
stamp-h1
libtirpc.pc
# file generated during compilation
*.o
.libs
lib*.a
src/libtirpc.la
src/libtirpc_la-*.lo
# generic editor backup et al
*~
# cscope database files
cscope.*
# files generated by patches
*.patch
*.rej
*.orig
# files generated by debugging
.gdb_history
.gdbinit
core

3
libtirpc/AUTHORS Normal file
View file

@ -0,0 +1,3 @@
Gilles Quillard <gilles.quillard@bull.net>
Antoine Fraticelli <antoine.fraticelli@bull.net>

359
libtirpc/COPYING Normal file
View file

@ -0,0 +1,359 @@
Sun Industry Standards Source License 1.0
DEFINITIONS
1.1. "Commercial Use" means distribution or otherwise
making the Original Code available to a third party.
1.2. "Contributor Version" means the combination of the
Original Code, and the Modifications made by that particular
Contributor.
1.3. "Electronic Distribution Mechanism" means a mechanism
generally accepted in the software development community for
the electronic transfer of data.
1.4. "Executable" means Original Code in any form other
than Source Code.
1.5. "Initial Developer" means the individual or entity
identified as the Initial Developer in the Source Code
notice required by 2 (Exhibit A)
1.6. "Larger Work" means a work which combines Original
Code or portions thereof with code not governed by the terms
of this License.
1.7. "License" means this document.
1.8. "Licensable" means having the right to grant, to the
maximum extent possible, whether at the time of the initial
grant or subsequently acquired, any and all of the rights
conveyed herein.
1.9. "Modifications" means any addition to or deletion from
the substance or structure of either the Original Code or
any previous Modifications. A Modification is:
A. Any addition to or deletion from the contents of a file
containing Original Code or previous Modifications.
B. Any new file that contains any part of the Original Code
or previous Modifications. .
1.10. "Original Code" means Source Code of computer
software code which is described in the Source Code notice
required by Exhibit A as Original Code.
1.11. "Patent Claims" means any patent claims, now owned or
hereafter acquired, including without limitation, method,
process, and apparatus claims, in any patent Licensable by
grantor.
1.12. "Source Code" means the preferred form of the
Original Code for making modifications to it, including all
modules it contains, plus any associated interface
definition files, or scripts used to control compilation and
installation of an Executable.
1.13. "Standards" means the standard identified in Exhibit
B or a subsequent version of such standard.
1.14. "You" or "Your" means an individual or a legal entity
exercising rights under, and complying with all of the terms
of, this License or a future version of this License issued
under Section 6.1. For legal entities, "You" includes any
entity which controls, is controlled by, or is under common
control with You. For purposes of this definition,
"control" means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by
contract or otherwise, or (b) ownership of more than fifty
percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2.0 SOURCE CODE LICENSE
2.1 The Initial Developer Grant: The Initial Developer
hereby grants You a world-wide, royalty-free, non-exclusive
license, subject to third party intellectual property
claims:
a) under intellectual property rights (other than patent or
trademark) Licensable by Initial Developer to use,
reproduce, modify, display, perform, sub license and
distribute the Original Code (or portions thereof )with or
without Modifications, and/or as part of a Larger Work; and
b) under Patents Claims infringed by the making, using or
selling of Original Code, to make, have made, use, practice,
sell, and offer for sale, and/or otherwise dispose of the
Original Code (or portions thereof).
c) the licenses granted in this Section 2.1(a ) and (b) are
effective on the date Initial Developer first distributes
Original Code under the terms of this License.
d) Notwithstanding Section 2.1(b )above, no patent license
is granted: 1) for code that You delete from the Original
Code; 2) separate from the Original Code; or 3) for
infringements caused by: i) the modification of the
Original Code or
ii) the combination of the Original Code with other software
or devices, including but not limited to Modifications.
3.0 DISTRIBUTION OBLIGATIONS
3.1 Application of License. The Source Code version of
Original Code may be distributed only under the terms of
this License or a future version of this License released
under Section 6.1, and You must include a copy of this
License with every copy of the Source Code You distribute.
You may not offer or impose any terms on any Source Code
version that alters or restricts the applicable version of
this License or the recipient's rights hereunder. Your
license for shipment of the Contributor Version is
conditioned upon your full compliance with this Section.
The Modifications which you create must comply with all
requirements set out by the Standards body in effect 120
days before You ship the Contributor Version. In the event
that the Modifications do not meet such requirements, You
agree to publish (i) any deviation from the Standards
protocol resulting from implementation of your Modifications
and (ii) a reference implementation of Your Modifications,
and to make any such deviation and reference implementation
available to all third parties under the same terms as the
license on a royalty free basis within thirty (30) days of
Your first customer shipment of Your Modifications.
3.2 Required Notices. You must duplicate the notice in
Exhibit A in each file of the Source Code. If it is not
possible to put such notice in a particular Source Code file
due to its structure, then You must include such notice in a
location (such as a relevant directory ) where a user would
be likely to look for such a notice. If You created one or
more Modifications ) You may add your name as a Contributor
to the notice described in Exhibit A. You must also
duplicate this License in any documentation for the Source
Code where You describe recipients' rights or ownership
rights relating to Initial Code. You may choose to offer,
and to charge a fee for, warranty, support, indemnity or
liability obligations to one or more recipients of Your
version of the Code. However, You may do so only
on Your own behalf, and not on behalf of the Initial
Developer. You must make it absolutely clear than any such
warranty, support, indemnity or liability obligation is
offered by You alone, and You hereby agree to indemnify the
Initial Developer for any liability incurred by the Initial
Developer as a result of warranty, support, indemnity or
liability terms You offer.
3.3 Distribution of Executable Versions. You may distribute
Original Code in Executable and Source form only if the
requirements of Section 3.1 and 3.2 have been met for that
Original Code, and if You include a notice stating that the
Source Code version of the Original Code is available under
the terms of this License. The notice must be conspicuously
included in any notice in an Executable or Source versions,
related documentation or collateral in which You describe
recipients' rights relating to the Original Code. You may
distribute the Executable and Source versions of Your
version of the Code or ownership rights under a license of
Your choice, which may contain terms different from this
License, provided that You are in compliance with the terms
of this License. If You distribute the Executable and
Source versions under a different license You must make it
absolutely clear that any terms which differ from this
License are offered by You alone, not by the Initial
Developer . You hereby agree to indemnify the Initial
Developer for any liability incurred by the Initial
Developer as a result of any such terms You offer .
3.4 Larger Works. You may create a Larger Work by combining
Original Code with other code not governed by the terms of
this License and distribute the Larger Work as a single
product. In such a case, You must make sure the
requirements of this License are fulfilled for the Original
Code.
4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION
If it is impossible for You to comply with any of the terms
of this License with respect to some or all of the Original
Code due to statute, judicial order, or regulation then You
must:
a) comply with the terms of this License to the maximum
extent possible; and
b) describe the limitations and the code they affect. Such
description must be included in the LEGAL file described in
Section 3.2 and must be included with all distributions of
the Source Code. Except to the extent prohibited by statute
or regulation, such description must be sufficiently
detailed for a recipient of ordinary skill to be able to
understand it.
5.0 APPLICATION OF THIS LICENSE This License applies to code
to which the Initial Developer has attached the notice in
Exhibit A and to related Modifications as set out in Section
3.1.
6.0 VERSIONS OF THE LICENSE
6.1 New Versions. Sun Microsystems, Inc. Sun may publish
revised and/or new versions of the License from time to
time. Each version will be given a distinguishing version
number .
6.2 Effect of New Versions. Once Original Code has been
published under a particular version of the License, You may
always continue to use it under the terms of that version.
You may also choose to use such Original Code under the
terms of any subsequent version of the License published by
Sun. No one other than Sun has the right to modify the
terms applicable to Original Code.
7. DISCLAIMER OF W ARRANTY. ORIGINAL CODE IS PROVIDED
UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY
ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
INITIAL DEVELOPER )ASSUME THE COST OF ANY NECESSARY
SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO
USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT
UNDER THIS DISCLAIMER.
8.0 TERMINATION
8.1 This License and the rights granted hereunder will
terminate automatically if You fail to comply with terms
herein and fail to cure such breach within 30 days of
becoming aware of the breach. All sublicenses to the
Original Code which are properly granted shall survive any
termination of this License. Provisions which, by their
nature, must remain in effect beyond the termination of this
License shall survive.
8.2 .In the event of termination under Section 8.1 above,
all end user license agreements (excluding distributors and
resellers) which have been validly granted by You or any
distributor hereunder prior to termination shall survive
termination.
9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO
LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE) ,CONTRACT,
OR OTHER WISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER
CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY
SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
LOSS OF GOOD WILL, WORK STOPPAGE, COMPUTER FAILURE OR
MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT
APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME
JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND
LIMITATION MAY NOT APPLY TO YOU.
10.0 U .S. GOVERNMENT END USERS U.S. Government: If this
Software is being acquired by or on behalf of the U.S.
Government or by a U.S. Government prime contractor or
subcontractor (at any tier), then the Government's rights in
the Software and accompanying documentation shall be only as
set forth in this license; this is in accordance with 48 C.F
.R. 227.7201 through 227.7202-4 (for Department of Defense
(DoD) acquisitions )and with 48 C.F.R.2.101 and 12.212( for
non-DoD acquisitions).
11.0 MISCELLANEOUS This License represents the complete
agreement concerning subject matter hereof. If any
provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to
make it enforceable. This License shall be governed by
California law provisions (except to the extent applicable
law, if any, provides otherwise), excluding its
conflict-of-law provisions. With respect to disputes in
which at least one party is a citizen of, or an entity
chartered or registered to do business in the United States
of America, any litigation relating to this License shall be
subject to the jurisdiction of the Federal Courts of the
Northern District of California, with venue lying in Santa
Clara County, California, with the losing party responsible
for costs, including without limitation, court costs and
reasonable attorneys fees and expenses. The application of
the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any law
or regulation which provides that the language of a contract
shall be construed against the drafter shall not apply to
this License.
EXHIBIT A - Sun Standards
"The contents of this file are subject to the Sun Standards
License Version 1.0 the (the "License";) You may not use
this file except in compliance with the License. You may
obtain a copy of the License at
_______________________________.
Software distributed under the License is distributed on
an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
express or implied. See the License for the specific
language governing rights and limitations under the License.
The Original Code is Copyright 1998 by Sun Microsystems, Inc
The Initial Developer of the Original Code is: Sun
Microsystems, Inc.
Portions created by _____________________________ are
Copyright ______________________________.
All Rights Reserved.
Contributors: ______________________________________.
EXHIBIT B - Sun Standards
The Standard is defined as the following IETF RFCs:
RFC1831: RPC: Remote Procedure Call Protocol Specification
Version 2 RFC1832: XDR: External Data REpresentation
Standard RFC1833: Binding Protocols for ONC RPC Version 2
RFC2078: Generic Security Service Application Program
Interface, Version 2 RFC2203: RPCSEC_GSS Protocol
Specification RFC2695: Authentication Mechanisms for ONC RPC
*
* Copyright (c) Copyright (c) Bull S.A. 2005 All Rights Reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

206
libtirpc/ChangeLog Normal file
View file

@ -0,0 +1,206 @@
2008-11-19 Steve Dickson <steved@redhat.com>
* Version 0.1.10 released.
commit 32ec5931e3debf208972d5146578f08dc113a9b6
Merge: 338af7f... 92cf0dd...
Author: Steve Dickson <steved@redhat.com>
Date: Mon Nov 17 12:26:22 2008 -0500
Merge branch 'master' of git://git.infradead.org/~steved/libtirpc
commit 92cf0dde310ca341a2f29ff66b19eeb9994a649a
Author: Ian Kent <ikent@redhat.com>
Date: Tue Oct 28 11:19:07 2008 -0400
Fixed a warings the IPV6 client routines
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 338af7f9f00e096b65a6d823f885c4eeaf1d1f8c
Author: Steve Dickson <steved@redhat.com>
Date: Mon Oct 27 12:46:54 2008 -0400
__rpc_taddr2uaddr_af() assumes the netbuf to always have a
non-zero data. This is a bad assumption and can lead to a
seg-fault. This patch adds a check for zero length and returns
NULL when found.
Signed-off-by: Steve Dickson <steved@redhat.com>
commit d9a5ae7079d001a9e3b9b384f9153f591a7158bd
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:10:43 2008 -0400
Fix __rpc_getconfip
__rpc_getconfip is supposed to return the first netconf
entry supporting tcp or udp, respectively. The code will
currently return the *last* entry, plus it will leak
memory when there is more than one such entry.
This patch fixes this issue.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 6c487efe74adb5c29f7bee5bd51b3ebef4968f7d
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:09:06 2008 -0400
Fix getpeereid
getpeereid fails because it uses an incorrect getsockopt call to obtain
the peer credentials on a AF_LOCAL socket. This in turn will cause all
RPC services to be registered with rpcbind to show up as having been
registered by "unknown".
This has a serious impact on security - a service owned by "unknown"
can essentially be unregistered (and thus replaced) by anyone.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 851b0f5c6dca22d634603f03f0a5e3e35c6db867
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:08:07 2008 -0400
svc_getcaller_netbuf macro seems broken
I haven't found any documentation, but the comment in the header
file seems to suggest that svc_getcaller_netbuf should return the
xp_rtaddr netbuf. Returning the address of the socket descripor
seems to be wrong at any rate.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit d94b92d5125242ce595c1baf42a1e6d1004b7756
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:06:54 2008 -0400
Introduce __rpc_set_netbuf helper
The RPC code contains a number of places where a netbuf
is initialized with some data. All the mem_alloc/memcpy
stuff is open-coded. Introduce a helper function and
convert the code.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit da5f9861ea3bae59c8eead26d38334721caa9f0a
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:05:20 2008 -0400
Kill map_ipv4_to_ipv6
After the change to svc_vc.c performed in the previous patch,
this function is no longer needed.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 59c374c4b507aeca957ed0096d98006edf601375
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 30 15:04:17 2008 -0400
Fix xp_raddr handling in svc_fd_create etc
Currently svc_fd_create tries to do some clever tricks
with IPv4/v6 address mapping.
This is broken for several reasons.
1. We don't want IPv4 based transport to look like IPv6
transports. Old applications compiled against tirpc
will expect AF_INET addresses, and are not equipped
to deal with AF_INET6.
2. There's a buffer overflow.
memcpy(&sin6, &ss, sizeof(ss));
copies a full struct sockaddr to a sockaddr_in6 on
the stack. Unlikely to be exploitable, but I wonder
if this ever worked....
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 628788c1cc84c86ee4cb36ee5d4fe8954e90fca5
Author: Steve Dickson <steved@redhat.com>
Date: Tue Sep 16 11:32:31 2008 -0400
- Fixed version-info in src/Makefile.am to reflect the correct version
- Fixed some of warnings in: src/auth_time.c, src/clnt_dg.c and
src/clnt_raw.c
- Added some #ifdef NOTUSED around some code in src/rpbc_clnt.c
that was not being used...
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 9e7ba0c7a02031294fefadfbca42b3dd5f2d841f
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 16 08:46:29 2008 -0400
Fix for taddr2addr conversion bug of local addresses
When converting af_local socket addresses in taddr2uaddr, an incorrect
sizeof() would result in a truncated path string. As a result,
rpcbind will report the local /var/lib/rpcbind address to clients
as "/v" on a 32bit machine.
Signed-off-by: okir@suse.de
Signed-off-by: Steve Dickson <steved@redhat.com>
commit ea9f048761d0b9a2ab6310bffa07351f0b04d8c5
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 2 12:11:15 2008 -0400
Always make IPv6 sockets V6ONLY
Assume you have a netconfig file looking like this:
udp tpi_clts v inet udp - -
udp6 tpi_clts v inet6 udp - -
...
a call to svc_tli_create(... &someaddr, "udp") will fail to create an
IPv6 server socket. The problem is that on Linux, passive IPv6 sockets
will also accept packets/connections from IPv4, and will simply map
the sender's address to an IPv6 mapped IPv4 address. So if you want to
bind both a UDPv4 and UDPv6 socket to the same port, this will fail with
EADDRINUSE.
The way to avoid this behavior is to change the socket to V6ONLY,
which tells the kernel to avoid the autmatic mapping.
The change proposed in the patch below does this. I *think* this is
a good place to do this, as it will also fix applications that do not
use svc_tli_create() - such as rpcbind, which creates the sockets on
its own using __rpc_nconf2fd.
I think this also improves portability, as BSD code assumes BSD
behavior, where this mapping does not occur either.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
commit 95c8f7227e6b15f2e430d7b87dadc95b2acd4a61
Author: Olaf Kirch <okir@suse.de>
Date: Tue Sep 2 12:09:39 2008 -0400
Fix incorrect sizeof() in __rpc_getbroadifs
__rpc_getbroadifs returns bad broadcast addresses on 32bit
machines because when copying the broadcast addresses, ite
applies the sizeof() operator to a pointer to a sockaddr,
rather than the sockaddr itself.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Steve Dickson <steved@redhat.com>
2004-10-13 Antoine Fraticelli <antoine.fraticellie@bull.net>
* Version 0.1 released.
2005-01-07 Gilles Quillard <Gilles.Quillard@bull.net>
* Version 0.1.5 Fix problems links to the use of Kerberos.

251
libtirpc/INSTALL Normal file
View file

@ -0,0 +1,251 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
TI-RPC Library Quick Installation
=================================
Without GSS API
$ ./configure
$ make
# make install
To enable utilization of RPCSEC via GSS API use following commands
but you need to install libgssapi from the CITI before
$ ./configure --enable-gss
$ make
# make install
Once installed, you can customize the /etc/netconfig configuration file
to configure the supported protocols. To support INET6 udp/tcp, uncomment
the udp6/tcp6 lines.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

36
libtirpc/Makefile.am Normal file
View file

@ -0,0 +1,36 @@
SUBDIRS = src man doc
nobase_include_HEADERS = tirpc/netconfig.h \
tirpc/rpcsvc/crypt.x \
tirpc/rpcsvc/crypt.h \
tirpc/rpc/xdr.h \
tirpc/rpc/types.h \
tirpc/rpc/svc_soc.h \
tirpc/rpc/svc.h \
tirpc/rpc/svc_dg.h \
tirpc/rpc/svc_auth.h \
tirpc/rpc/rpc_msg.h \
tirpc/rpc/rpc.h \
tirpc/rpc/rpcent.h \
tirpc/rpc/rpc_com.h \
tirpc/rpc/rpcb_prot.x \
tirpc/rpc/rpcb_prot.h \
tirpc/rpc/rpcb_clnt.h \
tirpc/rpc/raw.h \
tirpc/rpc/pmap_rmt.h \
tirpc/rpc/pmap_prot.h \
tirpc/rpc/pmap_clnt.h \
tirpc/rpc/nettype.h \
tirpc/rpc/des.h \
tirpc/rpc/des_crypt.h \
tirpc/rpc/clnt_stat.h \
tirpc/rpc/clnt_soc.h \
tirpc/rpc/clnt.h \
tirpc/rpc/auth_unix.h \
tirpc/rpc/auth_kerb.h \
tirpc/rpc/auth.h \
tirpc/rpc/auth_gss.h \
tirpc/rpc/auth_des.h
pkgconfigdir=$(libdir)/pkgconfig
pkgconfig_DATA = libtirpc.pc

3
libtirpc/NEWS Normal file
View file

@ -0,0 +1,3 @@
New in 0.1:
* Portage from FreeBSD 5.2.1 (security part to be completed)
* Use autoconf/automake

44
libtirpc/README Normal file
View file

@ -0,0 +1,44 @@
LIBTIRPC 0.1 FROM SUN'S TIRPCSRC 2.3 29 Aug 1994
This package contains SunLib's implementation of transport-independent
RPC (TI-RPC) documentation. This library forms a piece of the base of Open Network
Computing (ONC), and is derived directly from the Solaris 2.3 source.
TI-RPC is an enhanced version of TS-RPC that requires the UNIX System V
Transport Layer Interface (TLI) or an equivalent X/Open Transport Interface
(XTI). TI-RPC is on-the-wire compatible with the TS-RPC, which is supported
by almost 70 vendors on all major operating systems. TS-RPC source code
(RPCSRC 4.0) remains available from several internet sites.
This release was a native source release, compatible for
building on Solaris 2.3. It had been ported from FreeBSD 5.2.1 to GNU/Linux
in 2004.
Applications linked with this release's librpc must link with the United
States domestic version of libcrypt in order to resolve the cbc_crypt() and
ecb_crypt() functions. These routines are used with Secure RPC however all
RPC programs that link with this release's librpc will need to link with the
domestic libcrypt.
WHAT'S NEW IN THIS RELEASE: TIRPCSRC 2.3 FROM SUN
The previous release was TIRPCSRC 2.0.
1. This release is based on Solaris 2.3. The previous release was
based on Solaris 2.0. This release contains a siginificant number of
bug fixes and other enhancements over TIRPCSRC 2.0.
2. The RPC library is thread safe for all client-side interfaces
(clnt_create, clnt_call, etc.). The server-side interfaces
(svc_create, svc_run, etc.) are not thread safe in this release. The
server-side interfaces will be made thread safe in the next release of
TIRPCSRC. Please see the manual pages for details about which
interfaces are thread safe.
3. As part of the work to make the RPC library thread-safe, rpcgen has
been enhanced to generate thread-safe RPC stubs (the -M option). Note
that this modifies the call-signature for the stub functions; the
procedure calling the RPC stub must now pass to the stub a pointer to
an allocated structure where results will be placed by the stub. See
the rpcgen manual page and the rpcgen Programming Guide for details.

6
libtirpc/THANKS Normal file
View file

@ -0,0 +1,6 @@
Thanks to for
Aurelien Charbon <aurelien.charbon@bull.net> TI-RPC portage from NetBSD
BSD Communauty TI-RPC improvement from Sun implementation

3
libtirpc/TODO Normal file
View file

@ -0,0 +1,3 @@
* Support of DES & other security part
* Provide tests
* rpcgen command missing

7
libtirpc/VERSION Normal file
View file

@ -0,0 +1,7 @@
# This file is used by configure to get version information
#
PKG_MAJOR=0
PKG_MINOR=1
PKG_REVISION=11
PKG_BUILD=0

42
libtirpc/autogen.sh Normal file
View file

@ -0,0 +1,42 @@
#!/bin/sh -e
echo -n cleaning up .
# Clean up the generated crud
(
for FILE in compile config.guess config.sub depcomp install-sh ltmain.sh missing mkinstalldirs; do
if test -f $FILE; then
rm -f $FILE
fi
echo -n .
done
)
for FILE in aclocal.m4 configure config.h.in; do
if test -f $FILE; then
rm -f $FILE
fi
echo -n .
done
for DIR in autom4te.cache; do
if test -d $DIR; then
rm -rf $DIR
fi
echo -n .
done
find . -type f -name 'Makefile.in' -print0 | xargs -r0 rm -f --
find . -type f -name 'Makefile' -print0 | xargs -r0 rm -f --
echo ' done'
if test x"${1}" = x"clean"; then
exit
fi
aclocal
libtoolize --force --copy
autoheader
automake --add-missing --copy --gnu # -Wall
autoconf # -Wall

10
libtirpc/bootstrap Normal file
View file

@ -0,0 +1,10 @@
[ -e Makefile ] && make clean
rm -rf autom4te.cache configure Makefile stamp-h1
rm -rf src/Makefile src/.deps
rm -rf Makefile.in aclocal.m4 config.log config.h
rm -rf depcomp missing install-sh config.status
aclocal
autoheader
automake --gnu --add-missing -c
autoconf
rm -rf autom4te.cache config.log libtool stamp-h1*

29
libtirpc/configure.ac Normal file
View file

@ -0,0 +1,29 @@
AC_INIT(libtirpc, 0.2.1)
AM_INIT_AUTOMAKE(libtirpc, 0.2.1)
AM_MAINTAINER_MODE
AC_CONFIG_SRCDIR([src/auth_des.c])
AC_ARG_ENABLE(gss,[ --enable-gss Turn on gss api], [case "${enableval}" in
yes) gss=true ; AC_CHECK_LIB([gssapi],[gss_init_sec_context]) ;;
no) gss=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gss) ;;
esac],[gss=false])
AM_CONDITIONAL(GSS, test x$gss = xtrue)
if test x$gss = xtrue; then
AC_DEFINE(HAVE_LIBGSSAPI, 1, [])
PKG_CHECK_MODULES(GSSGLUE, libgssglue, [],
AC_MSG_ERROR([Unable to locate information required to use libgssglue.]))
fi
AC_PROG_CC
AM_CONFIG_HEADER(config.h)
AC_PROG_LIBTOOL
##AC_PROG_RANLIB
AC_HEADER_DIRENT
AC_PREFIX_DEFAULT(/usr)
AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h locale.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h])
AC_CHECK_LIB([pthread], [pthread_create])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile])
AC_OUTPUT(libtirpc.pc)

2
libtirpc/dirs Normal file
View file

@ -0,0 +1,2 @@
DIRS = src

5
libtirpc/doc/Makefile.am Normal file
View file

@ -0,0 +1,5 @@
install: install-am
$(mkinstalldirs) $(DESTDIR)/etc
cp -p ./etc_netconfig $(DESTDIR)/etc/netconfig
chmod 0644 $(DESTDIR)/etc/netconfig

View file

@ -0,0 +1,19 @@
#
# The network configuration file. This file is currently only used in
# conjunction with the TI-RPC code in the libtirpc library.
#
# Entries consist of:
#
# <network_id> <semantics> <flags> <protofamily> <protoname> \
# <device> <nametoaddr_libs>
#
# The <device> and <nametoaddr_libs> fields are always empty in this
# implementation.
#
udp tpi_clts v inet udp - -
tcp tpi_cots_ord v inet tcp - -
udp6 tpi_clts v inet6 udp - -
tcp6 tpi_cots_ord v inet6 tcp - -
rawip tpi_raw - inet - - -
local tpi_cots_ord - loopback - - -
unix tpi_cots_ord - loopback - - -

11
libtirpc/libtirpc.pc.in Normal file
View file

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libtirpc
Description: Transport Independent RPC Library
Requires:
Version: @PACKAGE_VERSION@
Libs: -L@libdir@ -ltirpc
Cflags: -I@includedir@/tirpc

View file

@ -0,0 +1,94 @@
LIBRARY libtirpc
EXPORTS
authnone_create
authunix_create
authunix_create_default
clnt_create
clnt_broadcast
clnt_pcreateerror
clnt_perrno
clnt_perror
clnt_spcreateerror
clnt_sperrno
clnt_sperror
clnt_tli_create
clntraw_create
clnttcp_create
clntudp_bufcreate
clntudp_create
freenetbuf
freenetconfigent
freeuaddr
get_myaddress
getnetconfigent
pmap_getmaps
pmap_getport
pmap_rmtcall
pmap_set
pmap_unset
svc_getreq
svc_getreqset
svc_run
svc_sendreply
svcerr_auth
svcerr_decode
svcerr_noproc
svcerr_noprog
svcerr_progvers
svcerr_systemerr
svcerr_weakauth
svcraw_create
svctcp_create
svcudp_bufcreate
svcudp_create
taddr2uaddr
tsd_key_delete
uaddr2taddr
xdr_array
xdr_authunix_parms
xdr_bool
xdr_bytes
xdr_callhdr
xdr_callmsg
xdr_char
xdr_des_block
xdr_double
xdr_enum
xdr_float
xdr_free
xdr_hyper
xdr_int
xdr_long
xdr_netobj
xdr_opaque
xdr_opaque_auth
xdr_pmap
xdr_pmaplist
xdr_pmaplist_ptr
xdr_pointer
xdr_reference
xdr_replymsg
xdr_short
xdr_string
xdr_u_char
xdr_u_hyper
xdr_u_int
xdr_u_int32_t
xdr_u_int64_t
xdr_u_long
xdr_u_short
xdr_union
xdr_vector
xdr_void
xdr_wrapstring
xdrmem_create
xdrrec_create
xdrrec_endofrecord
xdrrec_eof
xdrrec_skiprecord
xdrstdio_create
xprt_register
xprt_unregister
svc_fdset DATA
rpc_createerr DATA
_null_auth DATA

View file

@ -0,0 +1,61 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by tirpc.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

9
libtirpc/man/Makefile.am Normal file
View file

@ -0,0 +1,9 @@
man5_MANS = netconfig.5
man3_MANS = bindresvport.3t des_crypt.3t getnetconfig.3t getnetpath.3t \
getrpcent.3t getrpcport.3t rpc.3t rpc_clnt_auth.3t rpc_clnt_calls.3t \
rpc_clnt_create.3t rpc_secure.3t rpc_soc.3t rpc_svc_calls.3t \
rpc_svc_create.3t rpc_svc_err.3t rpc_svc_reg.3t rpc_xdr.3t rtime.3t
EXTRA_DIST = $(man5_MANS) $(man3_MANS)

View file

@ -0,0 +1,101 @@
.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
.\"
.Dd November 22, 1987
.Dt BINDRESVPORT 3
.Os
.Sh NAME
.Nm bindresvport ,
.Nm bindresvport_sa
.Nd bind a socket to a privileged IP port
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In rpc/rpc.h
.Ft int
.Fn bindresvport "int sd" "struct sockaddr_in *sin"
.Ft int
.Fn bindresvport_sa "int sd" "struct sockaddr *sa"
.Sh DESCRIPTION
The
.Fn bindresvport
and
.Fn bindresvport_sa
functions
are used to bind a socket descriptor to a privileged
.Tn IP
port, that is, a
port number in the range 0-1023.
.Pp
If
.Fa sin
is a pointer to a
.Ft "struct sockaddr_in"
then the appropriate fields in the structure should be defined.
Note that
.Fa sin->sin_family
must be initialized to the address family of the socket, passed by
.Fa sd .
If
.Fa sin->sin_port
is
.Sq 0
then an anonymous port (in the range 600-1023) will be
chosen, and if
.Xr bind 2
is successful, the
.Fa sin->sin_port
will be updated to contain the allocated port.
.Pp
If
.Fa sin
is the
.Dv NULL
pointer,
an anonymous port will be allocated (as above).
However, there is no way for
.Fn bindresvport
to return the allocated port in this case.
.Pp
Only root can bind to a privileged port; this call will fail for any
other users.
.Pp
Function prototype of
.Fn bindresvport
is biased to
.Dv AF_INET
socket.
The
.Fn bindresvport_sa
function
acts exactly the same, with more neutral function prototype.
Note that both functions behave exactly the same, and
both support
.Dv AF_INET6
sockets as well as
.Dv AF_INET
sockets.
.Sh RETURN VALUES
.Rv -std bindresvport
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EPFNOSUPPORT
If second argument was supplied,
and address family did not match between arguments.
.El
.Pp
The
.Fn bindresvport
function
may also fail and set
.Va errno
for any of the errors specified for the calls
.Xr bind 2 ,
.Xr getsockopt 2 ,
or
.Xr setsockopt 2 .
.Sh SEE ALSO
.Xr bind 2 ,
.Xr getsockopt 2 ,
.Xr setsockopt 2 ,
.Xr ip 4

129
libtirpc/man/des_crypt.3t Normal file
View file

@ -0,0 +1,129 @@
.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI;
.\"
.Dd October 6, 1987
.Dt DES_CRYPT 3
.Os
.Sh NAME
.Nm des_crypt , ecb_crypt , cbc_crypt , des_setparity
.Nd "fast DES encryption"
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/des_crypt.h
.Ft int
.Fn ecb_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode"
.Ft int
.Fn cbc_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode" "char *ivec"
.Ft void
.Fn des_setparity "char *key"
.Sh DESCRIPTION
The
.Fn ecb_crypt
and
.Fn cbc_crypt
functions
implement the
.Tn NBS
.Tn DES
(Data Encryption Standard).
These routines are faster and more general purpose than
.Xr crypt 3 .
They also are able to utilize
.Tn DES
hardware if it is available.
The
.Fn ecb_crypt
function
encrypts in
.Tn ECB
(Electronic Code Book)
mode, which encrypts blocks of data independently.
The
.Fn cbc_crypt
function
encrypts in
.Tn CBC
(Cipher Block Chaining)
mode, which chains together
successive blocks.
.Tn CBC
mode protects against insertions, deletions and
substitutions of blocks.
Also, regularities in the clear text will
not appear in the cipher text.
.Pp
Here is how to use these routines.
The first argument,
.Fa key ,
is the 8-byte encryption key with parity.
To set the key's parity, which for
.Tn DES
is in the low bit of each byte, use
.Fn des_setparity .
The second argument,
.Fa data ,
contains the data to be encrypted or decrypted.
The
third argument,
.Fa datalen ,
is the length in bytes of
.Fa data ,
which must be a multiple of 8.
The fourth argument,
.Fa mode ,
is formed by
.Em OR Ns 'ing
together some things.
For the encryption direction
.Em OR
in either
.Dv DES_ENCRYPT
or
.Dv DES_DECRYPT .
For software versus hardware
encryption,
.Em OR
in either
.Dv DES_HW
or
.Dv DES_SW .
If
.Dv DES_HW
is specified, and there is no hardware, then the encryption is performed
in software and the routine returns
.Er DESERR_NOHWDEVICE .
For
.Fn cbc_crypt ,
the
.Fa ivec
argument
is the 8-byte initialization
vector for the chaining.
It is updated to the next initialization
vector upon return.
.Sh ERRORS
.Bl -tag -width [DESERR_NOHWDEVICE] -compact
.It Bq Er DESERR_NONE
No error.
.It Bq Er DESERR_NOHWDEVICE
Encryption succeeded, but done in software instead of the requested hardware.
.It Bq Er DESERR_HWERR
An error occurred in the hardware or driver.
.It Bq Er DESERR_BADPARAM
Bad argument to routine.
.El
.Pp
Given a result status
.Va stat ,
the macro
.Fn DES_FAILED stat
is false only for the first two statuses.
.Sh SEE ALSO
.\" .Xr des 1 ,
.Xr crypt 3
.Sh RESTRICTIONS
These routines are not available in RPCSRC 4.0.
This information is provided to describe the
.Tn DES
interface expected by
Secure RPC.

View file

@ -0,0 +1,220 @@
.\" @(#)getnetconfig.3n 1.28 93/06/02 SMI; from SVr4
.\" Copyright 1989 AT&T
.Dd April 22, 2000
.Dt GETNETCONFIG 3
.Os
.Sh NAME
.Nm getnetconfig ,
.Nm setnetconfig ,
.Nm endnetconfig ,
.Nm getnetconfigent ,
.Nm freenetconfigent ,
.Nm nc_perror ,
.Nm nc_sperror
.Nd get network configuration database entry
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In netconfig.h
.Ft "struct netconfig *"
.Fn getnetconfig "void *handlep"
.Ft "void *"
.Fn setnetconfig "void"
.Ft int
.Fn endnetconfig "void *handlep"
.Ft "struct netconfig *"
.Fn getnetconfigent "const char *netid"
.Ft void
.Fn freenetconfigent "struct netconfig *netconfigp"
.Ft void
.Fn nc_perror "const char *msg"
.Ft "char *"
.Fn nc_sperror "void"
.Sh DESCRIPTION
The library routines described on this page
provide the application access to
the system network configuration database,
.Pa /etc/netconfig .
The
.Fn getnetconfig
function
returns a pointer to the
current entry in the
netconfig
database, formatted as a
.Ft "struct netconfig" .
Successive calls will return successive netconfig
entries in the netconfig database.
The
.Fn getnetconfig
function
can be used to search the entire netconfig
file.
The
.Fn getnetconfig
function
returns
.Dv NULL
at the end of the file.
The
.Fa handlep
argument
is the handle obtained through
.Fn setnetconfig .
.Pp
A call to
.Fn setnetconfig
has the effect of
.Dq binding
to or
.Dq rewinding
the netconfig database.
The
.Fn setnetconfig
function
must be called before the first call to
.Fn getnetconfig
and may be called at any other time.
The
.Fn setnetconfig
function
need not be called before a call to
.Fn getnetconfigent .
The
.Fn setnetconfig
function
returns a unique handle to be used by
.Fn getnetconfig .
.Pp
The
.Fn endnetconfig
function
should be called when processing is complete to release resources for reuse.
The
.Fa handlep
argument
is the handle obtained through
.Fn setnetconfig .
Programmers should be aware, however, that the last call to
.Fn endnetconfig
frees all memory allocated by
.Fn getnetconfig
for the
.Ft "struct netconfig"
data structure.
The
.Fn endnetconfig
function
may not be called before
.Fn setnetconfig .
.Pp
The
.Fn getnetconfigent
function
returns a pointer
to the netconfig structure corresponding
to
.Fa netid .
It returns
.Dv NULL
if
.Fa netid
is invalid
(that is, does not name an entry in the netconfig database).
.Pp
The
.Fn freenetconfigent
function
frees the netconfig structure pointed to by
.Fa netconfigp
(previously returned by
.Fn getnetconfigent ) .
.Pp
The
.Fn nc_perror
function
prints a message to the standard error indicating why any of the
above routines failed.
The message is prepended with the string
.Fa msg
and a colon.
A newline character is appended at the end of the message.
.Pp
The
.Fn nc_sperror
function
is similar to
.Fn nc_perror
but instead of sending the message
to the standard error, will return a pointer to a string that
contains the error message.
.Pp
The
.Fn nc_perror
and
.Fn nc_sperror
functions
can also be used with the
.Ev NETPATH
access routines defined in
.Xr getnetpath 3 .
.Sh RETURN VALUES
The
.Fn setnetconfig
function
returns a unique handle to be used by
.Fn getnetconfig .
In the case of an error,
.Fn setnetconfig
returns
.Dv NULL
and
.Fn nc_perror
or
.Fn nc_sperror
can be used to print the reason for failure.
.Pp
The
.Fn getnetconfig
function
returns a pointer to the current entry in the netconfig
database, formatted as a
.Ft "struct netconfig" .
The
.Fn getnetconfig
function
returns
.Dv NULL
at the end of the file, or upon failure.
.Pp
The
.Fn endnetconfig
function
returns 0 on success and \-1 on failure
(for example, if
.Fn setnetconfig
was not called previously).
.Pp
On success,
.Fn getnetconfigent
returns a pointer to the
.Ft "struct netconfig"
structure corresponding to
.Fa netid ;
otherwise it returns
.Dv NULL .
.Pp
The
.Fn nc_sperror
function
returns a pointer to a buffer which contains the error message string.
This buffer is overwritten on each call.
In multithreaded applications, this buffer is
implemented as thread-specific data.
.Sh FILES
.Bl -tag -width /etc/netconfig -compact
.It Pa /etc/netconfig
.El
.Sh SEE ALSO
.Xr getnetpath 3 ,
.Xr netconfig 5

168
libtirpc/man/getnetpath.3t Normal file
View file

@ -0,0 +1,168 @@
.\" @(#)getnetpath.3n 1.26 93/05/07 SMI; from SVr4
.\" Copyright 1989 AT&T
.Dd April 22, 2000
.Dt GETNETPATH 3
.Os
.Sh NAME
.Nm getnetpath ,
.Nm setnetpath ,
.Nm endnetpath
.Nd get
.Pa /etc/netconfig
entry corresponding to
.Ev NETPATH
component
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In netconfig.h
.Ft "struct netconfig *"
.Fn getnetpath "void *handlep"
.Ft "void *"
.Fn setnetpath "void"
.Ft int
.Fn endnetpath "void *handlep"
.Sh DESCRIPTION
The routines described in this page provide the application access to the system
network configuration database,
.Pa /etc/netconfig ,
as it is
.Dq filtered
by the
.Ev NETPATH
environment variable (see
.Xr environ 7 ) .
See
.Xr getnetconfig 3
for other routines that also access the
network configuration database directly.
The
.Ev NETPATH
variable is a list of colon-separated network identifiers.
.Pp
The
.Fn getnetpath
function
returns a pointer to the
netconfig database entry corresponding to the first valid
.Ev NETPATH
component.
The netconfig entry is formatted as a
.Ft "struct netconfig" .
On each subsequent call,
.Fn getnetpath
returns a pointer to the netconfig entry that corresponds to the next
valid
.Ev NETPATH
component.
The
.Fn getnetpath
function
can thus be used to search the netconfig database for all networks
included in the
.Ev NETPATH
variable.
When
.Ev NETPATH
has been exhausted,
.Fn getnetpath
returns
.Dv NULL .
.Pp
A call to
.Fn setnetpath
.Dq binds
to or
.Dq rewinds
.Ev NETPATH .
The
.Fn setnetpath
function
must be called before the first call to
.Fn getnetpath
and may be called at any other time.
It returns a handle that is used by
.Fn getnetpath .
.Pp
The
.Fn getnetpath
function
silently ignores invalid
.Ev NETPATH
components.
A
.Ev NETPATH
component is invalid if there is no corresponding
entry in the netconfig database.
.Pp
If the
.Ev NETPATH
variable is unset,
.Fn getnetpath
behaves as if
.Ev NETPATH
were set to the sequence of
.Dq default
or
.Dq visible
networks in the netconfig database, in the
order in which they are listed.
.\"This proviso holds also for this
.\"whole manpage.
.Pp
The
.Fn endnetpath
function
may be called to
.Dq unbind
from
.Ev NETPATH
when processing is complete, releasing resources for reuse.
Programmers should be aware, however, that
.Fn endnetpath
frees all memory allocated by
.Fn getnetpath
for the struct netconfig data structure.
.Sh RETURN VALUES
The
.Fn setnetpath
function
returns a handle that is used by
.Fn getnetpath .
In case of an error,
.Fn setnetpath
returns
.Dv NULL .
.Pp
The
.Fn endnetpath
function
returns 0 on success and \-1 on failure
(for example, if
.Fn setnetpath
was not called previously).
The
.Fn nc_perror
or
.Fn nc_sperror
function
can be used to print out the reason for failure.
See
.Xr getnetconfig 3 .
.Pp
When first called,
.Fn getnetpath
returns a pointer to the netconfig database entry corresponding to the first
valid
.Ev NETPATH
component.
When
.Ev NETPATH
has been exhausted,
.Fn getnetpath
returns
.Dv NULL .
.Sh SEE ALSO
.Xr getnetconfig 3 ,
.Xr netconfig 5 ,
.Xr environ 7

106
libtirpc/man/getrpcent.3t Normal file
View file

@ -0,0 +1,106 @@
.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
.\"
.Dd December 14, 1987
.Dt GETRPCENT 3
.Os
.Sh NAME
.Nm getrpcent ,
.Nm getrpcbyname ,
.Nm getrpcbynumber ,
.Nm endrpcent ,
.Nm setrpcent
.Nd get RPC entry
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft struct rpcent *
.Fn getrpcent void
.Ft struct rpcent *
.Fn getrpcbyname "char *name"
.Ft struct rpcent *
.Fn getrpcbynumber "int number"
.Ft void
.Fn setrpcent "int stayopen"
.Ft void
.Fn endrpcent void
.Sh DESCRIPTION
The
.Fn getrpcent ,
.Fn getrpcbyname ,
and
.Fn getrpcbynumber
functions
each return a pointer to an object with the
following structure
containing the broken-out
fields of a line in the rpc program number data base,
.Pa /etc/rpc :
.Bd -literal
struct rpcent {
char *r_name; /* name of server for this rpc program */
char **r_aliases; /* alias list */
long r_number; /* rpc program number */
};
.Ed
.Pp
The members of this structure are:
.Bl -tag -width r_aliases -offset indent
.It Va r_name
The name of the server for this rpc program.
.It Va r_aliases
A zero terminated list of alternate names for the rpc program.
.It Va r_number
The rpc program number for this service.
.El
.Pp
The
.Fn getrpcent
function
reads the next line of the file, opening the file if necessary.
.Pp
The
.Fn setrpcent
function
opens and rewinds the file. If the
.Fa stayopen
flag is non-zero,
the net data base will not be closed after each call to
.Fn getrpcent
(either directly, or indirectly through one of
the other
.Dq getrpc
calls).
.Pp
The
.Fn endrpcent
function
closes the file.
.Pp
The
.Fn getrpcbyname
and
.Fn getrpcbynumber
functions
sequentially search from the beginning
of the file until a matching rpc program name or
program number is found, or until end-of-file is encountered.
.Sh FILES
.Bl -tag -width /etc/rpc -compact
.It Pa /etc/rpc
.El
.Sh SEE ALSO
.Xr rpc 5 ,
.Xr rpcinfo 8 ,
.Xr ypserv 8
.Sh DIAGNOSTICS
A
.Dv NULL
pointer is returned on
.Dv EOF
or error.
.Sh BUGS
All information
is contained in a static area
so it must be copied if it is
to be saved.

View file

@ -0,0 +1,34 @@
.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
.\"
.Dd October 6, 1987
.Dt GETRPCPORT 3
.Os
.Sh NAME
.Nm getrpcport
.Nd get RPC port number
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.Ft int
.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto"
.Sh DESCRIPTION
The
.Fn getrpcport
function
returns the port number for version
.Fa versnum
of the RPC program
.Fa prognum
running on
.Fa host
and using protocol
.Fa proto .
It returns 0 if it cannot contact the portmapper, or if
.Fa prognum
is not registered. If
.Fa prognum
is registered but not with version
.Fa versnum ,
it will still return a port number (for some version of the program)
indicating that the program is indeed registered.
The version mismatch will be detected upon the first call to the service.

123
libtirpc/man/netconfig.5 Normal file
View file

@ -0,0 +1,123 @@
.Dd November 17, 2000
.Dt NETCONFIG 5
.Os
.Sh NAME
.Nm netconfig
.Nd network configuration data base
.Sh SYNOPSIS
.Pa /etc/netconfig
.Sh DESCRIPTION
The
.Nm
file defines a list of
.Dq transport names ,
describing their semantics and protocol.
In
.Fx ,
this file is only used by the RPC library code.
.Pp
Entries have the following format:
.Pp
.Ar network_id semantics flags family protoname device libraries
.Pp
Entries consist of the following fields:
.Bl -tag -width network_id
.It Ar network_id
The name of the transport described.
.It Ar semantics
Describes the semantics of the transport.
This can be one of:
.Bl -tag -width tpi_cots_ord -offset indent
.It Sy tpi_clts
Connectionless transport.
.It Sy tpi_cots
Connection-oriented transport
.It Sy tpi_cots_ord
Connection-oriented, ordered transport.
.It Sy tpi_raw
A raw connection.
.El
.It Ar flags
This field is either blank (specified by
.Dq Li - ) ,
or contains a
.Dq Li v ,
meaning visible to the
.Xr getnetconfig 3
function.
.It Ar family
The protocol family of the transport.
This is currently one of:
.Bl -tag -width loopback -offset indent
.It Sy inet6
The IPv6
.Pq Dv PF_INET6
family of protocols.
.It Sy inet
The IPv4
.Pq Dv PF_INET
family of protocols.
.It Sy loopback
The
.Dv PF_LOCAL
protocol family.
.El
.It Ar protoname
The name of the protocol used for this transport.
Can currently be either
.Sy udp ,
.Sy tcp
or empty.
.It Ar device
This field is always empty in
.Fx .
.It Ar libraries
This field is always empty in
.Fx .
.El
.Pp
The order of entries in this file will determine which transport will
be preferred by the RPC library code, given a match on a specified
network type.
For example, if a sample network config file would look like this:
.Bd -literal -offset indent
udp6 tpi_clts v inet6 udp - -
tcp6 tpi_cots_ord v inet6 tcp - -
udp tpi_clts v inet udp - -
tcp tpi_cots_ord v inet tcp - -
rawip tpi_raw - inet - - -
local tpi_cots_ord - loopback - - -
.Ed
.Pp
then using the network type
.Sy udp
in calls to the RPC library function (see
.Xr rpc 3 )
will make the code first try
.Sy udp6 ,
and then
.Sy udp .
.Pp
.Xr getnetconfig 3
and associated functions will parse this file and return structures of
the following format:
.Bd -literal
struct netconfig {
char *nc_netid; /* Network ID */
unsigned long nc_semantics; /* Semantics (see below) */
unsigned long nc_flag; /* Flags (see below) */
char *nc_protofmly; /* Protocol family */
char *nc_proto; /* Protocol name */
char *nc_device; /* Network device pathname (unused) */
unsigned long nc_nlookups; /* Number of lookup libs (unused) */
char **nc_lookups; /* Names of the libraries (unused) */
unsigned long nc_unused[9]; /* reserved */
};
.Ed
.Sh FILES
.Bl -tag -width /etc/netconfig -compact
.It Pa /etc/netconfig
.El
.Sh SEE ALSO
.Xr getnetconfig 3 ,
.Xr getnetpath 3

52
libtirpc/man/publickey.3t Normal file
View file

@ -0,0 +1,52 @@
.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC
.\"
.Dd October 6, 1987
.Dt PUBLICKEY 3
.Os
.Sh NAME
.Nm publickey , getpublickey , getsecretkey
.Nd "get public or secret key"
.Sh LIBRARY
.Lb librpcsvc
.Sh SYNOPSIS
.In rpc/rpc.h
.In rpc/key_prot.h
.Ft int
.Fo getpublickey
.Fa "char netname[MAXNETNAMELEN+1]"
.Fa "char publickey[HEXKEYBYTES+1]"
.Fc
.Ft int
.Fo getsecretkey
.Fa "char netname[MAXNETNAMELEN+1]"
.Fa "char secretkey[HEXKEYBYTES+1]"
.Fa "char *passwd"
.Fc
.Sh DESCRIPTION
These routines are used to get public and secret keys from the
.Tn YP
database.
The
.Fn getsecretkey
function
has an extra argument,
.Fa passwd ,
which is used to decrypt the encrypted secret key stored in the database.
Both routines return 1 if they are successful in finding the key, 0 otherwise.
The keys are returned as
.Dv NULL Ns \-terminated ,
hexadecimal strings.
If the password supplied to
.Fn getsecretkey
fails to decrypt the secret key, the routine will return 1 but the
.Fa secretkey
argument will be a
.Dv NULL
string
.Pq Dq .
.Sh SEE ALSO
.Xr publickey 5
.Pp
.%T "RPC Programmer's Manual"
in
.Pa /usr/share/doc/psd/23.rpc .

41
libtirpc/man/publickey.5 Normal file
View file

@ -0,0 +1,41 @@
.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI;
.Dd October 19, 1987
.Dt PUBLICKEY 5
.Os
.Sh NAME
.Nm publickey
.Nd "public key database"
.Sh SYNOPSIS
.Pa /etc/publickey
.Sh DESCRIPTION
.Pa /etc/publickey
is the public key database used for secure
RPC (Remote Procedure Calls).
Each entry in
the database consists of a network user
name (which may either refer to
a user or a hostname), followed by the user's
public key (in hex
notation), a colon, and then the user's
secret key encrypted with
its login password (also in hex notation).
.Pp
This file is altered either by the user through the
.Xr chkey 1
command or by the system administrator through the
.Xr newkey 8
command.
The file
.Pa /etc/publickey
should only contain data on the
.Tn NIS
master machine, where it
is converted into the
.Tn NIS
database
.Pa publickey.byname .
.Sh SEE ALSO
.Xr chkey 1 ,
.Xr publickey 3 ,
.Xr newkey 8 ,
.Xr ypupdated 8

515
libtirpc/man/rpc.3t Normal file
View file

@ -0,0 +1,515 @@
.\" @(#)rpc.3n 1.31 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.Dd May 7, 1993
.Dt RPC 3
.Os
.Sh NAME
.Nm rpc
.Nd library routines for remote procedure calls
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.In netconfig.h
.Sh DESCRIPTION
These
routines allow C language programs to make procedure
calls on other machines across a network.
First, the client sends a request to the server.
On receipt of the request, the server calls a dispatch routine
to perform the requested service, and then sends back a reply.
.Pp
All
RPC routines require the header
.In rpc/rpc.h .
Routines that take a
.Vt "struct netconfig"
also require that
.In netconfig.h
be included.
.Sh Nettype
Some of the high-level
RPC interface routines take a
.Fa nettype
string as one of the arguments
(for example,
.Fn clnt_create ,
.Fn svc_create ,
.Fn rpc_reg ,
.Fn rpc_call ) .
This string defines a class of transports which can be used
for a particular application.
.Pp
The
.Fa nettype
argument
can be one of the following:
.Bl -tag -width datagram_v
.It netpath
Choose from the transports which have been
indicated by their token names in the
.Ev NETPATH
environment variable.
.Ev NETPATH
is unset or
.Dv NULL ,
it defaults to
.Qq visible .
.Qq netpath
is the default
.Fa nettype .
.It visible
Choose the transports which have the visible flag (v)
set in the
.Pa /etc/netconfig
file.
.It circuit_v
This is same as
.Qq visible
except that it chooses only the connection oriented transports
(semantics
.Qq tpi_cots
or
.Qq tpi_cots_ord )
from the entries in the
.Pa /etc/netconfig
file.
.It datagram_v
This is same as
.Qq visible
except that it chooses only the connectionless datagram transports
(semantics
.Qq tpi_clts )
from the entries in the
.Pa /etc/netconfig
file.
.It circuit_n
This is same as
.Qq netpath
except that it chooses only the connection oriented datagram transports
(semantics
.Qq tpi_cots
or
.Qq tpi_cots_ord ) .
.It datagram_n
This is same as
.Qq netpath
except that it chooses only the connectionless datagram transports
(semantics
.Qq tpi_clts ) .
.It udp
This refers to Internet UDP, both version 4 and 6.
.It tcp
This refers to Internet TCP, both version 4 and 6.
.El
.Pp
If
.Fa nettype
is
.Dv NULL ,
it defaults to
.Qq netpath .
The transports are tried in left to right order in the
.Ev NETPATH
variable or in top to down order in the
.Pa /etc/netconfig
file.
.Sh Derived Types
The derived types used in the RPC interfaces are defined as follows:
.Bd -literal
typedef u_int32_t rpcprog_t;
typedef u_int32_t rpcvers_t;
typedef u_int32_t rpcproc_t;
typedef u_int32_t rpcprot_t;
typedef u_int32_t rpcport_t;
typedef int32_t rpc_inline_t;
.Ed
.Sh "Data Structures"
Some of the data structures used by the
RPC package are shown below.
.Sh "The AUTH Structure"
.Bd -literal
/*
* Authentication info. Opaque to client.
*/
struct opaque_auth {
enum_t oa_flavor; /* flavor of auth */
caddr_t oa_base; /* address of more auth stuff */
u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
};
/*
* Auth handle, interface to client side authenticators.
*/
typedef struct {
struct opaque_auth ah_cred;
struct opaque_auth ah_verf;
struct auth_ops {
void (*ah_nextverf)(\|);
int (*ah_marshal)(\|); /* nextverf & serialize */
int (*ah_validate)(\|); /* validate verifier */
int (*ah_refresh)(\|); /* refresh credentials */
void (*ah_destroy)(\|); /* destroy this structure */
} *ah_ops;
caddr_t ah_private;
} AUTH;
.Ed
.Sh "The CLIENT Structure"
.Bd -literal
/*
* Client rpc handle.
* Created by individual implementations.
* Client is responsible for initializing auth.
*/
typedef struct {
AUTH *cl_auth; /* authenticator */
struct clnt_ops {
enum clnt_stat (*cl_call)(); /* call remote procedure */
void (*cl_abort)(); /* abort a call */
void (*cl_geterr)(); /* get specific error code */
bool_t (*cl_freeres)(); /* frees results */
void (*cl_destroy)(); /* destroy this structure */
bool_t (*cl_control)(); /* the ioctl() of rpc */
} *cl_ops;
caddr_t cl_private; /* private stuff */
char *cl_netid; /* network identifier */
char *cl_tp; /* device name */
} CLIENT;
.Ed
.Sh "The SVCXPRT structure"
.Bd -literal
enum xprt_stat {
XPRT_DIED,
XPRT_MOREREQS,
XPRT_IDLE
};
/*
* Server side transport handle
*/
typedef struct {
int xp_fd; /* file descriptor for the server handle */
u_short xp_port; /* obsolete */
const struct xp_ops {
bool_t (*xp_recv)(); /* receive incoming requests */
enum xprt_stat (*xp_stat)(); /* get transport status */
bool_t (*xp_getargs)(); /* get arguments */
bool_t (*xp_reply)(); /* send reply */
bool_t (*xp_freeargs)(); /* free mem allocated for args */
void (*xp_destroy)(); /* destroy this struct */
} *xp_ops;
int xp_addrlen; /* length of remote addr. Obsolete */
struct sockaddr_in xp_raddr; /* Obsolete */
const struct xp_ops2 {
bool_t (*xp_control)(); /* catch-all function */
} *xp_ops2;
char *xp_tp; /* transport provider device name */
char *xp_netid; /* network identifier */
struct netbuf xp_ltaddr; /* local transport address */
struct netbuf xp_rtaddr; /* remote transport address */
struct opaque_auth xp_verf; /* raw response verifier */
caddr_t xp_p1; /* private: for use by svc ops */
caddr_t xp_p2; /* private: for use by svc ops */
caddr_t xp_p3; /* private: for use by svc lib */
int xp_type /* transport type */
} SVCXPRT;
.Ed
.Sh "The svc_reg structure"
.Bd -literal
struct svc_req {
rpcprog_t rq_prog; /* service program number */
rpcvers_t rq_vers; /* service protocol version */
rpcproc_t rq_proc; /* the desired procedure */
struct opaque_auth rq_cred; /* raw creds from the wire */
caddr_t rq_clntcred; /* read only cooked cred */
SVCXPRT *rq_xprt; /* associated transport */
};
.Ed
.Sh "The XDR structure"
.Bd -literal
/*
* XDR operations.
* XDR_ENCODE causes the type to be encoded into the stream.
* XDR_DECODE causes the type to be extracted from the stream.
* XDR_FREE can be used to release the space allocated by an XDR_DECODE
* request.
*/
enum xdr_op {
XDR_ENCODE=0,
XDR_DECODE=1,
XDR_FREE=2
};
/*
* This is the number of bytes per unit of external data.
*/
#define BYTES_PER_XDR_UNIT (4)
#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) /
BYTES_PER_XDR_UNIT) \e * BYTES_PER_XDR_UNIT)
/*
* A xdrproc_t exists for each data type which is to be encoded or
* decoded. The second argument to the xdrproc_t is a pointer to
* an opaque pointer. The opaque pointer generally points to a
* structure of the data type to be decoded. If this points to 0,
* then the type routines should allocate dynamic storage of the
* appropriate size and return it.
* bool_t (*xdrproc_t)(XDR *, caddr_t *);
*/
typedef bool_t (*xdrproc_t)();
/*
* The XDR handle.
* Contains operation which is being applied to the stream,
* an operations vector for the particular implementation
*/
typedef struct {
enum xdr_op x_op; /* operation; fast additional param */
struct xdr_ops {
bool_t (*x_getlong)(); /* get a long from underlying stream */
bool_t (*x_putlong)(); /* put a long to underlying stream */
bool_t (*x_getbytes)(); /* get bytes from underlying stream */
bool_t (*x_putbytes)(); /* put bytes to underlying stream */
u_int (*x_getpostn)(); /* returns bytes off from beginning */
bool_t (*x_setpostn)(); /* lets you reposition the stream */
long * (*x_inline)(); /* buf quick ptr to buffered data */
void (*x_destroy)(); /* free privates of this xdr_stream */
} *x_ops;
caddr_t x_public; /* users' data */
caddr_t x_private; /* pointer to private data */
caddr_t x_base; /* private used for position info */
u_int x_handy; /* extra private word */
} XDR;
/*
* The netbuf structure. This structure is defined in <xti.h> on SysV
* systems, but NetBSD / FreeBSD do not use XTI.
*
* Usually, buf will point to a struct sockaddr, and len and maxlen
* will contain the length and maximum length of that socket address,
* respectively.
*/
struct netbuf {
unsigned int maxlen;
unsigned int len;
void *buf;
};
/*
* The format of the address and options arguments of the XTI t_bind call.
* Only provided for compatibility, it should not be used other than
* as an argument to svc_tli_create().
*/
struct t_bind {
struct netbuf addr;
unsigned int qlen;
};
.Ed
.Sh "Index to Routines"
The following table lists RPC routines and the manual reference
pages on which they are described:
.Pp
.Bl -tag -width "authunix_create_default()" -compact
.It Em "RPC Routine"
.Em "Manual Reference Page"
.Pp
.It Fn auth_destroy
.Xr rpc_clnt_auth 3
.It Fn authdes_create
.Xr rpc_soc 3
.It Fn authnone_create
.Xr rpc_clnt_auth 3
.It Fn authsys_create
.Xr rpc_clnt_auth 3
.It Fn authsys_create_default
.Xr rpc_clnt_auth 3
.It Fn authunix_create
.Xr rpc_soc 3
.It Fn authunix_create_default
.Xr rpc_soc 3
.It Fn callrpc
.Xr rpc_soc 3
.It Fn clnt_broadcast
.Xr rpc_soc 3
.It Fn clnt_call
.Xr rpc_clnt_calls 3
.It Fn clnt_control
.Xr rpc_clnt_create 3
.It Fn clnt_create
.Xr rpc_clnt_create 3
.It Fn clnt_create_timed
.Xr rpc_clnt_create 3
.It Fn clnt_create_vers
.Xr rpc_clnt_create 3
.It Fn clnt_create_vers_timed
.Xr rpc_clnt_create 3
.It Fn clnt_destroy
.Xr rpc_clnt_create 3
.It Fn clnt_dg_create
.Xr rpc_clnt_create 3
.It Fn clnt_freeres
.Xr rpc_clnt_calls 3
.It Fn clnt_geterr
.Xr rpc_clnt_calls 3
.It Fn clnt_pcreateerror
.Xr rpc_clnt_create 3
.It Fn clnt_perrno
.Xr rpc_clnt_calls 3
.It Fn clnt_perror
.Xr rpc_clnt_calls 3
.It Fn clnt_raw_create
.Xr rpc_clnt_create 3
.It Fn clnt_spcreateerror
.Xr rpc_clnt_create 3
.It Fn clnt_sperrno
.Xr rpc_clnt_calls 3
.It Fn clnt_sperror
.Xr rpc_clnt_calls 3
.It Fn clnt_tli_create
.Xr rpc_clnt_create 3
.It Fn clnt_tp_create
.Xr rpc_clnt_create 3
.It Fn clnt_tp_create_timed
.Xr rpc_clnt_create 3
.It Fn clnt_udpcreate
.Xr rpc_soc 3
.It Fn clnt_vc_create
.Xr rpc_clnt_create 3
.It Fn clntraw_create
.Xr rpc_soc 3
.It Fn clnttcp_create
.Xr rpc_soc 3
.It Fn clntudp_bufcreate
.Xr rpc_soc 3
.It Fn get_myaddress
.Xr rpc_soc 3
.It Fn pmap_getmaps
.Xr rpc_soc 3
.It Fn pmap_getport
.Xr rpc_soc 3
.It Fn pmap_rmtcall
.Xr rpc_soc 3
.It Fn pmap_set
.Xr rpc_soc 3
.It Fn pmap_unset
.Xr rpc_soc 3
.It Fn registerrpc
.Xr rpc_soc 3
.It Fn rpc_broadcast
.Xr rpc_clnt_calls 3
.It Fn rpc_broadcast_exp
.Xr rpc_clnt_calls 3
.It Fn rpc_call
.Xr rpc_clnt_calls 3
.It Fn rpc_reg
.Xr rpc_svc_calls 3
.It Fn svc_create
.Xr rpc_svc_create 3
.It Fn svc_destroy
.Xr rpc_svc_create 3
.It Fn svc_dg_create
.Xr rpc_svc_create 3
.It Fn svc_dg_enablecache
.Xr rpc_svc_calls 3
.It Fn svc_fd_create
.Xr rpc_svc_create 3
.It Fn svc_fds
.Xr rpc_soc 3
.It Fn svc_freeargs
.Xr rpc_svc_reg 3
.It Fn svc_getargs
.Xr rpc_svc_reg 3
.It Fn svc_getcaller
.Xr rpc_soc 3
.It Fn svc_getreq
.Xr rpc_soc 3
.It Fn svc_getreqset
.Xr rpc_svc_calls 3
.It Fn svc_getrpccaller
.Xr rpc_svc_calls 3
.It Fn svc_kerb_reg
.Xr kerberos_rpc 3
.It Fn svc_raw_create
.Xr rpc_svc_create 3
.It Fn svc_reg
.Xr rpc_svc_calls 3
.It Fn svc_register
.Xr rpc_soc 3
.It Fn svc_run
.Xr rpc_svc_reg 3
.It Fn svc_sendreply
.Xr rpc_svc_reg 3
.It Fn svc_tli_create
.Xr rpc_svc_create 3
.It Fn svc_tp_create
.Xr rpc_svc_create 3
.It Fn svc_unreg
.Xr rpc_svc_calls 3
.It Fn svc_unregister
.Xr rpc_soc 3
.It Fn svc_vc_create
.Xr rpc_svc_create 3
.It Fn svcerr_auth
.Xr rpc_svc_err 3
.It Fn svcerr_decode
.Xr rpc_svc_err 3
.It Fn svcerr_noproc
.Xr rpc_svc_err 3
.It Fn svcerr_noprog
.Xr rpc_svc_err 3
.It Fn svcerr_progvers
.Xr rpc_svc_err 3
.It Fn svcerr_systemerr
.Xr rpc_svc_err 3
.It Fn svcerr_weakauth
.Xr rpc_svc_err 3
.It Fn svcfd_create
.Xr rpc_soc 3
.It Fn svcraw_create
.Xr rpc_soc 3
.It Fn svctcp_create
.Xr rpc_soc 3
.It Fn svcudp_bufcreate
.Xr rpc_soc 3
.It Fn svcudp_create
.Xr rpc_soc 3
.It Fn xdr_accepted_reply
.Xr rpc_xdr 3
.It Fn xdr_authsys_parms
.Xr rpc_xdr 3
.It Fn xdr_authunix_parms
.Xr rpc_soc 3
.It Fn xdr_callhdr
.Xr rpc_xdr 3
.It Fn xdr_callmsg
.Xr rpc_xdr 3
.It Fn xdr_opaque_auth
.Xr rpc_xdr 3
.It Fn xdr_rejected_reply
.Xr rpc_xdr 3
.It Fn xdr_replymsg
.Xr rpc_xdr 3
.It Fn xprt_register
.Xr rpc_svc_calls 3
.It Fn xprt_unregister
.Xr rpc_svc_calls 3
.El
.Sh FILES
.Bl -tag -width /etc/netconfig
.It Pa /etc/netconfig
.El
.Sh SEE ALSO
.Xr getnetconfig 3 ,
.Xr getnetpath 3 ,
.Xr rpcbind 3 ,
.Xr rpc_clnt_auth 3 ,
.Xr rpc_clnt_calls 3 ,
.Xr rpc_clnt_create 3 ,
.Xr rpc_svc_calls 3 ,
.Xr rpc_svc_create 3 ,
.Xr rpc_svc_err 3 ,
.Xr rpc_svc_reg 3 ,
.Xr rpc_xdr 3 ,
.Xr xdr 3 ,
.Xr netconfig 5

57
libtirpc/man/rpc.5 Normal file
View file

@ -0,0 +1,57 @@
.\" @(#)rpc.4 1.17 93/08/30 SMI; from SVr4
.\" Copyright 1989 AT&T
.Dd December 10, 1991
.Dt RPC 5
.Os
.Sh NAME
.Nm rpc
.Nd rpc program number data base
.Sh SYNOPSIS
.Pa /etc/rpc
.Sh DESCRIPTION
The
.Nm
file contains user readable names that
can be used in place of RPC program numbers.
For each RPC program a single line should be present
with the following information:
.Pp
.Bl -enum -compact
.It
name of the RPC program
.It
RPC program number
.It
aliases
.El
.Pp
Items are separated by any number of blanks and/or
tab characters.
A hash
.Pq Dq Li #
indicates the beginning of a comment; characters up to the end of
the line are not interpreted by routines which search the file.
.Sh EXAMPLES
Below is an example of an RPC database:
.Bd -literal
#
# rpc
#
rpcbind 100000 portmap sunrpc portmapper
rusersd 100002 rusers
nfs 100003 nfsprog
mountd 100005 mount showmount
walld 100008 rwall shutdown
sprayd 100012 spray
llockmgr 100020
nlockmgr 100021
status 100024
bootparam 100026
keyserv 100029 keyserver
.Ed
.Sh FILES
.Bl -tag -width /etc/nsswitch.conf -compact
.It Pa /etc/nsswitch.conf
.El
.Sh SEE ALSO
.Xr getrpcent 3

View file

@ -0,0 +1,96 @@
.\" @(#)rpc_clnt_auth.3n 1.21 93/05/07 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_clnt_auth 1.4 89/07/20 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $NetBSD: rpc_clnt_auth.3,v 1.1 2000/06/03 09:29:50 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_auth.3,v 1.5 2002/12/19 09:40:23 ru Exp $
.Dd May 7, 1993
.Dt RPC_CLNT_AUTH 3
.Os
.Sh NAME
.Nm auth_destroy ,
.Nm authnone_create ,
.Nm authsys_create ,
.Nm authsys_create_default
.Nd library routines for client side remote procedure call authentication
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft "void"
.Fn auth_destroy "AUTH *auth"
.Ft "AUTH *"
.Fn authnone_create "void"
.Ft "AUTH *"
.Fn authsys_create "const char *host" "const uid_t uid" "const gid_t gid" "const int len" "const gid_t *aup_gids"
.Ft "AUTH *"
.Fn authsys_create_default "void"
.Sh DESCRIPTION
These routines are part of the
RPC library that allows C language programs to make procedure
calls on other machines across the network,
with desired authentication.
.Pp
These routines are normally called after creating the
.Vt CLIENT
handle.
The
.Va cl_auth
field of the
.Vt CLIENT
structure should be initialized by the
.Vt AUTH
structure returned by some of the following routines.
The client's authentication information
is passed to the server when the
RPC
call is made.
.Pp
Only the
.Dv NULL
and the
.Dv SYS
style of authentication is discussed here.
.Sh Routines
.Bl -tag -width authsys_create_default()
.It Fn auth_destroy
A function macro that destroys the authentication
information associated with
.Fa auth .
Destruction usually involves deallocation
of private data structures.
The use of
.Fa auth
is undefined after calling
.Fn auth_destroy .
.It Fn authnone_create
Create and return an RPC
authentication handle that passes nonusable
authentication information with each remote procedure call.
This is the default authentication used by RPC.
.It Fn authsys_create
Create and return an RPC authentication handle that contains
.Dv AUTH_SYS
authentication information.
The
.Fa host
argument
is the name of the machine on which the information was
created;
.Fa uid
is the user's user ID;
.Fa gid
is the user's current group ID;
.Fa len
and
.Fa aup_gids
refer to a counted array of groups to which the user belongs.
.It Fn authsys_create_default
Call
.Fn authsys_create
with the appropriate arguments.
.El
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr rpc_clnt_calls 3 ,
.Xr rpc_clnt_create 3

View file

@ -0,0 +1,316 @@
.\" @(#)rpc_clnt_calls.3n 1.30 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_clnt_calls 1.4 89/07/20 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_calls.3,v 1.7 2002/12/19 09:40:23 ru Exp $
.Dd May 7, 1993
.Dt RPC_CLNT_CALLS 3
.Os
.Sh NAME
.Nm rpc_clnt_calls ,
.Nm clnt_call ,
.Nm clnt_freeres ,
.Nm clnt_geterr ,
.Nm clnt_perrno ,
.Nm clnt_perror ,
.Nm clnt_sperrno ,
.Nm clnt_sperror ,
.Nm rpc_broadcast ,
.Nm rpc_broadcast_exp ,
.Nm rpc_call
.Nd library routines for client side calls
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft "enum clnt_stat"
.Fn clnt_call "CLIENT *clnt" "const rpcproc_t procnum" "const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "caddr_t out" "const struct timeval tout"
.Ft bool_t
.Fn clnt_freeres "CLIENT *clnt" "const xdrproc_t outproc" "caddr_t out"
.Ft void
.Fn clnt_geterr "const CLIENT * clnt" "struct rpc_err * errp"
.Ft void
.Fn clnt_perrno "const enum clnt_stat stat"
.Ft void
.Fn clnt_perror "CLIENT *clnt" "const char *s"
.Ft "char *"
.Fn clnt_sperrno "const enum clnt_stat stat"
.Ft "char *"
.Fn clnt_sperror "CLIENT *clnt" "const char * s"
.Ft "enum clnt_stat"
.Fo rpc_broadcast
.Fa "const rpcprog_t prognum" "const rpcvers_t versnum"
.Fa "const rpcproc_t procnum" "const xdrproc_t inproc"
.Fa "const caddr_t in" "const xdrproc_t outproc" "caddr_t out"
.Fa "const resultproc_t eachresult" "const char *nettype"
.Fc
.Ft "enum clnt_stat"
.Fo rpc_broadcast_exp
.Fa "const rpcprog_t prognum" "const rpcvers_t versnum"
.Fa "const rpcproc_t procnum" "const xdrproc_t xargs"
.Fa "caddr_t argsp" "const xdrproc_t xresults"
.Fa "caddr_t resultsp" "const resultproc_t eachresult"
.Fa "const int inittime" "const int waittime"
.Fa "const char * nettype"
.Fc
.Ft "enum clnt_stat"
.Fo rpc_call
.Fa "const char *host" "const rpcprog_t prognum"
.Fa "const rpcvers_t versnum" "const rpcproc_t procnum"
.Fa "const xdrproc_t inproc" "const char *in"
.Fa "const xdrproc_t outproc" "char *out" "const char *nettype"
.Fc
.Sh DESCRIPTION
RPC library routines allow C language programs to make procedure
calls on other machines across the network.
First, the client calls a procedure to send a request to the server.
Upon receipt of the request, the server calls a dispatch routine
to perform the requested service, and then sends back a reply.
.Pp
The
.Fn clnt_call ,
.Fn rpc_call ,
and
.Fn rpc_broadcast
routines handle the client side of the procedure call.
The remaining routines deal with error handling in the case of errors.
.Pp
Some of the routines take a
.Vt CLIENT
handle as one of the arguments.
A
.Vt CLIENT
handle can be created by an RPC creation routine such as
.Fn clnt_create
(see
.Xr rpc_clnt_create 3 ) .
.Pp
These routines are safe for use in multithreaded applications.
.Vt CLIENT
handles can be shared between threads, however in this implementation
requests by different threads are serialized (that is, the first request will
receive its results before the second request is sent).
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt CLIENT
data structure.
.Bl -tag -width XXXXX
.It Fn clnt_call
A function macro that calls the remote procedure
.Fa procnum
associated with the client handle,
.Fa clnt ,
which is obtained with an RPC
client creation routine such as
.Fn clnt_create
(see
.Xr rpc_clnt_create 3 ) .
The
.Fa inproc
argument
is the XDR function used to encode the procedure's arguments, and
.Fa outproc
is the XDR function used to decode the procedure's results;
.Fa in
is the address of the procedure's argument(s), and
.Fa out
is the address of where to place the result(s).
The
.Fa tout
argument
is the time allowed for results to be returned, which is overridden by
a time-out set explicitly through
.Fn clnt_control ,
see
.Xr rpc_clnt_create 3 .
If the remote call succeeds, the status returned is
.Dv RPC_SUCCESS ,
otherwise an appropriate status is returned.
.It Fn clnt_freeres
A function macro that frees any data allocated by the
RPC/XDR system when it decoded the results of an RPC call.
The
.Fa out
argument
is the address of the results, and
.Fa outproc
is the XDR routine describing the results.
This routine returns 1 if the results were successfully freed,
and 0 otherwise.
.It Fn clnt_geterr
A function macro that copies the error structure out of the client
handle to the structure at address
.Fa errp .
.It Fn clnt_perrno
Print a message to standard error corresponding
to the condition indicated by
.Fa stat .
A newline is appended.
Normally used after a procedure call fails for a routine
for which a client handle is not needed, for instance
.Fn rpc_call .
.It Fn clnt_perror
Print a message to the standard error indicating why an
RPC call failed;
.Fa clnt
is the handle used to do the call.
The message is prepended with string
.Fa s
and a colon.
A newline is appended.
Normally used after a remote procedure call fails
for a routine which requires a client handle,
for instance
.Fn clnt_call .
.It Fn clnt_sperrno
Take the same arguments as
.Fn clnt_perrno ,
but instead of sending a message to the standard error
indicating why an RPC
call failed, return a pointer to a string which contains the message.
The
.Fn clnt_sperrno
function
is normally used instead of
.Fn clnt_perrno
when the program does not have a standard error (as a program
running as a server quite likely does not), or if the programmer
does not want the message to be output with
.Fn printf
(see
.Xr printf 3 ) ,
or if a message format different than that supported by
.Fn clnt_perrno
is to be used.
Note:
unlike
.Fn clnt_sperror
and
.Fn clnt_spcreateerror
(see
.Xr rpc_clnt_create 3 ) ,
.Fn clnt_sperrno
does not return pointer to static data so the
result will not get overwritten on each call.
.It Fn clnt_sperror
Like
.Fn clnt_perror ,
except that (like
.Fn clnt_sperrno )
it returns a string instead of printing to standard error.
However,
.Fn clnt_sperror
does not append a newline at the end of the message.
Warning:
returns pointer to a buffer that is overwritten
on each call.
.It Fn rpc_broadcast
Like
.Fn rpc_call ,
except the call message is broadcast to
all the connectionless transports specified by
.Fa nettype .
If
.Fa nettype
is
.Dv NULL ,
it defaults to
.Qq netpath .
Each time it receives a response,
this routine calls
.Fn eachresult ,
whose form is:
.Ft bool_t
.Fn eachresult "caddr_t out" "const struct netbuf * addr" "const struct netconfig * netconf"
where
.Fa out
is the same as
.Fa out
passed to
.Fn rpc_broadcast ,
except that the remote procedure's output is decoded there;
.Fa addr
points to the address of the machine that sent the results, and
.Fa netconf
is the netconfig structure of the transport on which the remote
server responded.
If
.Fn eachresult
returns 0,
.Fn rpc_broadcast
waits for more replies;
otherwise it returns with appropriate status.
Warning:
broadcast file descriptors are limited in size to the
maximum transfer size of that transport.
For Ethernet, this value is 1500 bytes.
The
.Fn rpc_broadcast
function
uses
.Dv AUTH_SYS
credentials by default (see
.Xr rpc_clnt_auth 3 ) .
.It Fn rpc_broadcast_exp
Like
.Fn rpc_broadcast ,
except that the initial timeout,
.Fa inittime
and the maximum timeout,
.Fa waittime
are specified in milliseconds.
The
.Fa inittime
argument
is the initial time that
.Fn rpc_broadcast_exp
waits before resending the request.
After the first resend, the re-transmission interval
increases exponentially until it exceeds
.Fa waittime .
.It Fn rpc_call
Call the remote procedure associated with
.Fa prognum ,
.Fa versnum ,
and
.Fa procnum
on the machine,
.Fa host .
The
.Fa inproc
argument
is used to encode the procedure's arguments, and
.Fa outproc
is used to decode the procedure's results;
.Fa in
is the address of the procedure's argument(s), and
.Fa out
is the address of where to place the result(s).
The
.Fa nettype
argument
can be any of the values listed on
.Xr rpc 3 .
This routine returns
.Dv RPC_SUCCESS
if it succeeds,
or an appropriate status is returned.
Use the
.Fn clnt_perrno
routine to translate failure status into error messages.
Warning:
.Fn rpc_call
uses the first available transport belonging
to the class
.Fa nettype ,
on which it can create a connection.
You do not have control of timeouts or authentication
using this routine.
.El
.Sh SEE ALSO
.Xr printf 3 ,
.Xr rpc 3 ,
.Xr rpc_clnt_auth 3 ,
.Xr rpc_clnt_create 3

View file

@ -0,0 +1,514 @@
.\" @(#)rpc_clnt_create.3n 1.36 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_clnt_create 1.5 89/07/24 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $NetBSD: rpc_clnt_create.3,v 1.2 2000/06/20 00:53:08 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_create.3,v 1.12 2003/09/14 13:41:56 ru Exp $
.Dd May 7, 1993
.Dt RPC_CLNT_CREATE 3
.Os
.Sh NAME
.Nm rpc_clnt_create ,
.Nm clnt_control ,
.Nm clnt_create ,
.Nm clnt_create_timed ,
.Nm clnt_create_vers ,
.Nm clnt_create_vers_timed ,
.Nm clnt_destroy ,
.Nm clnt_dg_create ,
.Nm clnt_pcreateerror ,
.Nm clnt_raw_create ,
.Nm clnt_spcreateerror ,
.Nm clnt_tli_create ,
.Nm clnt_tp_create ,
.Nm clnt_tp_create_timed ,
.Nm clnt_vc_create ,
.Nm rpc_createerr
.Nd "library routines for dealing with creation and manipulation of"
.Vt CLIENT
handles
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft bool_t
.Fn clnt_control "CLIENT *clnt" "const u_int req" "char *info"
.Ft "CLIENT *"
.Fn clnt_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
.Ft "CLIENT *"
.Fn clnt_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" "const struct timeval *timeout"
.Ft "CLIENT *"
.Fn clnt_create_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype"
.Ft "CLIENT *"
.Fn clnt_create_vers_timed "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "char *nettype" "const struct timeval *timeout"
.Ft void
.Fn clnt_destroy "CLIENT *clnt"
.Ft "CLIENT *"
.Fn clnt_dg_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
.Ft void
.Fn clnt_pcreateerror "const char *s"
.Ft "char *"
.Fn clnt_spcreateerror "const char *s"
.Ft "CLIENT *"
.Fn clnt_raw_create "const rpcprog_t prognum" "const rpcvers_t versnum"
.Ft "CLIENT *"
.Fn clnt_tli_create "const int fildes" "const struct netconfig *netconf" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
.Ft "CLIENT *"
.Fn clnt_tp_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
.Ft "CLIENT *"
.Fn clnt_tp_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct timeval *timeout"
.Ft "CLIENT *"
.Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "u_int sendsz" "u_int recvsz"
.Sh DESCRIPTION
RPC library routines allow C language programs to make procedure
calls on other machines across the network.
First a
.Vt CLIENT
handle is created and then the client calls a procedure to send a
request to the server.
On receipt of the request, the server calls a dispatch routine
to perform the requested service, and then sends a reply.
.Sh Routines
.Bl -tag -width YYYYYYY
.It Fn clnt_control
A function macro to change or retrieve various information
about a client object.
The
.Fa req
argument
indicates the type of operation, and
.Fa info
is a pointer to the information.
For both connectionless and connection-oriented transports,
the supported values of
.Fa req
and their argument types and what they do are:
.Bl -column "CLSET_FD_NCLOSE" "struct timeval *" "set total timeout"
.It Dv CLSET_TIMEOUT Ta "struct timeval *" Ta "set total timeout"
.It Dv CLGET_TIMEOUT Ta "struct timeval *" Ta "get total timeout"
.El
.Pp
Note:
if you set the timeout using
.Fn clnt_control ,
the timeout argument passed by
.Fn clnt_call
is ignored in all subsequent calls.
.Pp
Note:
If you set the timeout value to 0,
.Fn clnt_control
immediately returns an error
.Pq Dv RPC_TIMEDOUT .
Set the timeout argument to 0 for batching calls.
.Bl -column CLSET_FD_NCLOSE "struct timeval *" "do not close fd on destroy"
.It Dv CLGET_SVC_ADDR Ta "struct netbuf *" Ta "get servers address"
.It Dv CLGET_FD Ta "int *" Ta "get fd from handle"
.It Dv CLSET_FD_CLOSE Ta "void" Ta "close fd on destroy"
.It Dv CLSET_FD_NCLOSE Ta void Ta "don't close fd on destroy"
.It Dv CLGET_VERS Ta "u_int32_t *" Ta "get RPC program version"
.It Dv CLSET_VERS Ta "u_int32_t *" Ta "set RPC program version"
.It Dv CLGET_XID Ta "u_int32_t *" Ta "get XID of previous call"
.It Dv CLSET_XID Ta "u_int32_t *" Ta "set XID of next call"
.El
.Pp
The following operations are valid for connectionless transports only:
.Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout"
.It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout"
.It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout"
.It Dv CLSET_CONNECT Ta Vt "int *" Ta use Xr connect 2
.El
.Pp
The retry timeout is the time that RPC
waits for the server to reply before retransmitting the request.
The
.Fn clnt_control
function
returns
.Dv TRUE
on success and
.Dv FALSE
on failure.
.It Fn clnt_create
Generic client creation routine for program
.Fa prognum
and version
.Fa versnum .
The
.Fa host
argument
identifies the name of the remote host where the server
is located.
The
.Fa nettype
argument
indicates the class of transport protocol to use.
The transports are tried in left to right order in
.Ev NETPATH
environment variable or in top to bottom order in
the netconfig database.
The
.Fn clnt_create
function
tries all the transports of the
.Fa nettype
class available from the
.Ev NETPATH
environment variable and the netconfig database,
and chooses the first successful one.
A default timeout is set and can be modified using
.Fn clnt_control .
This routine returns
.Dv NULL
if it fails.
The
.Fn clnt_pcreateerror
routine can be used to print the reason for failure.
.Pp
Note:
.Fn clnt_create
returns a valid client handle even
if the particular version number supplied to
.Fn clnt_create
is not registered with the
.Xr rpcbind 8
service.
This mismatch will be discovered by a
.Fn clnt_call
later (see
.Xr rpc_clnt_calls 3 ) .
.It Fn clnt_create_timed
Generic client creation routine which is similar to
.Fn clnt_create
but which also has the additional argument
.Fa timeout
that specifies the maximum amount of time allowed for
each transport class tried.
In all other respects, the
.Fn clnt_create_timed
call behaves exactly like the
.Fn clnt_create
call.
.It Fn clnt_create_vers
Generic client creation routine which is similar to
.Fn clnt_create
but which also checks for the
version availability.
The
.Fa host
argument
identifies the name of the remote host where the server
is located.
The
.Fa nettype
argument
indicates the class transport protocols to be used.
If the routine is successful it returns a client handle created for
the highest version between
.Fa vers_low
and
.Fa vers_high
that is supported by the server.
The
.Fa vers_outp
argument
is set to this value.
That is, after a successful return
.Fa vers_low
<=
.Fa *vers_outp
<=
.Fa vers_high .
If no version between
.Fa vers_low
and
.Fa vers_high
is supported by the server then the routine fails and returns
.Dv NULL .
A default timeout is set and can be modified using
.Fn clnt_control .
This routine returns
.Dv NULL
if it fails.
The
.Fn clnt_pcreateerror
routine can be used to print the reason for failure.
Note:
.Fn clnt_create
returns a valid client handle even
if the particular version number supplied to
.Fn clnt_create
is not registered with the
.Xr rpcbind 8
service.
This mismatch will be discovered by a
.Fn clnt_call
later (see
.Xr rpc_clnt_calls 3 ) .
However,
.Fn clnt_create_vers
does this for you and returns a valid handle
only if a version within
the range supplied is supported by the server.
.It Fn clnt_create_vers_timed
Generic client creation routine which is similar to
.Fn clnt_create_vers
but which also has the additional argument
.Fa timeout
that specifies the maximum amount of time allowed for
each transport class tried.
In all other respects, the
.Fn clnt_create_vers_timed
call behaves exactly like the
.Fn clnt_create_vers
call.
.It Fn clnt_destroy
A function macro that destroys the client's RPC handle.
Destruction usually involves deallocation
of private data structures, including
.Fa clnt
itself.
Use of
.Fa clnt
is undefined after calling
.Fn clnt_destroy .
If the RPC library opened the associated file descriptor, or
.Dv CLSET_FD_CLOSE
was set using
.Fn clnt_control ,
the file descriptor will be closed.
The caller should call
.Fn auth_destroy "clnt->cl_auth"
(before calling
.Fn clnt_destroy )
to destroy the associated
.Vt AUTH
structure (see
.Xr rpc_clnt_auth 3 ) .
.It Fn clnt_dg_create
This routine creates an RPC client for the remote program
.Fa prognum
and version
.Fa versnum ;
the client uses a connectionless transport.
The remote program is located at address
.Fa svcaddr .
The
.Fa fildes
argument
is an open and bound file descriptor.
This routine will resend the call message in intervals of
15 seconds until a response is received or until the
call times out.
The total time for the call to time out is specified by
.Fn clnt_call
(see
.Fn clnt_call
in
.Xr rpc_clnt_calls 3 ) .
The retry time out and the total time out periods can
be changed using
.Fn clnt_control .
The user may set the size of the send and receive
buffers with the
.Fa sendsz
and
.Fa recvsz
arguments;
values of 0 choose suitable defaults.
This routine returns
.Dv NULL
if it fails.
.It Fn clnt_pcreateerror
Print a message to standard error indicating
why a client RPC handle could not be created.
The message is prepended with the string
.Fa s
and a colon, and appended with a newline.
.It Fn clnt_spcreateerror
Like
.Fn clnt_pcreateerror ,
except that it returns a string
instead of printing to the standard error.
A newline is not appended to the message in this case.
Warning:
returns a pointer to a buffer that is overwritten
on each call.
.It Fn clnt_raw_create
This routine creates an RPC
client handle for the remote program
.Fa prognum
and version
.Fa versnum .
The transport used to pass messages to the service is
a buffer within the process's address space,
so the corresponding RPC
server should live in the same address space;
(see
.Fn svc_raw_create
in
.Xr rpc_svc_create 3 ) .
This allows simulation of RPC and measurement of
RPC overheads, such as round trip times,
without any kernel or networking interference.
This routine returns
.Dv NULL
if it fails.
The
.Fn clnt_raw_create
function
should be called after
.Fn svc_raw_create .
.It Fn clnt_tli_create
This routine creates an RPC
client handle for the remote program
.Fa prognum
and version
.Fa versnum .
The remote program is located at address
.Fa svcaddr .
If
.Fa svcaddr
is
.Dv NULL
and it is connection-oriented, it is assumed that the file descriptor
is connected.
For connectionless transports, if
.Fa svcaddr
is
.Dv NULL ,
.Dv RPC_UNKNOWNADDR
error is set.
The
.Fa fildes
argument
is a file descriptor which may be open, bound and connected.
If it is
.Dv RPC_ANYFD ,
it opens a file descriptor on the transport specified by
.Fa netconf .
If
.Fa fildes
is
.Dv RPC_ANYFD
and
.Fa netconf
is
.Dv NULL ,
a
.Dv RPC_UNKNOWNPROTO
error is set.
If
.Fa fildes
is unbound, then it will attempt to bind the descriptor.
The user may specify the size of the buffers with the
.Fa sendsz
and
.Fa recvsz
arguments;
values of 0 choose suitable defaults.
Depending upon the type of the transport (connection-oriented
or connectionless),
.Fn clnt_tli_create
calls appropriate client creation routines.
This routine returns
.Dv NULL
if it fails.
The
.Fn clnt_pcreateerror
routine can be used to print the reason for failure.
The remote rpcbind
service (see
.Xr rpcbind 8 )
is not consulted for the address of the remote
service.
.It Fn clnt_tp_create
Like
.Fn clnt_create
except
.Fn clnt_tp_create
tries only one transport specified through
.Fa netconf .
The
.Fn clnt_tp_create
function
creates a client handle for the program
.Fa prognum ,
the version
.Fa versnum ,
and for the transport specified by
.Fa netconf .
Default options are set,
which can be changed using
.Fn clnt_control
calls.
The remote rpcbind service on the host
.Fa host
is consulted for the address of the remote service.
This routine returns
.Dv NULL
if it fails.
The
.Fn clnt_pcreateerror
routine can be used to print the reason for failure.
.It Fn clnt_tp_create_timed
Like
.Fn clnt_tp_create
except
.Fn clnt_tp_create_timed
has the extra argument
.Fa timeout
which specifies the maximum time allowed for
the creation attempt to succeed.
In all other respects, the
.Fn clnt_tp_create_timed
call behaves exactly like the
.Fn clnt_tp_create
call.
.It Fn clnt_vc_create
This routine creates an RPC
client for the remote program
.Fa prognum
and version
.Fa versnum ;
the client uses a connection-oriented transport.
The remote program is located at address
.Fa svcaddr .
The
.Fa fildes
argument
is an open and bound file descriptor.
The user may specify the size of the send and receive buffers
with the
.Fa sendsz
and
.Fa recvsz
arguments;
values of 0 choose suitable defaults.
This routine returns
.Dv NULL
if it fails.
The address
.Fa svcaddr
should not be
.Dv NULL
and should point to the actual address of the remote program.
The
.Fn clnt_vc_create
function
does not consult the remote rpcbind service for this information.
.It Xo
.Vt "struct rpc_createerr" Va rpc_createerr ;
.Xc
A global variable whose value is set by any RPC
client handle creation routine
that fails.
It is used by the routine
.Fn clnt_pcreateerror
to print the reason for the failure.
.El
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr rpc_clnt_auth 3 ,
.Xr rpc_clnt_calls 3 ,
.Xr rpcbind 8

279
libtirpc/man/rpc_secure.3t Normal file
View file

@ -0,0 +1,279 @@
.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
.\" $FreeBSD: src/lib/libc/rpc/rpc_secure.3,v 1.14 2002/12/19 09:40:23 ru Exp $
.\"
.Dd February 16, 1988
.Dt RPC 3
.Os
.Sh NAME
.Nm rpc_secure
.Nd library routines for secure remote procedure calls
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft AUTH *
.Fo authdes_create
.Fa "char *name"
.Fa "unsigned window"
.Fa "struct sockaddr *addr"
.Fa "des_block *ckey"
.Fc
.Ft int
.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups"
.Ft int
.Fn getnetname "char *name"
.Ft int
.Fn host2netname "char *name" "const char *host" "const char *domain"
.Ft int
.Fn key_decryptsession "const char *remotename" "des_block *deskey"
.Ft int
.Fn key_encryptsession "const char *remotename" "des_block *deskey"
.Ft int
.Fn key_gendes "des_block *deskey"
.Ft int
.Fn key_setsecret "const char *key"
.Ft int
.Fn netname2host "char *name" "char *host" "int hostlen"
.Ft int
.Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist"
.Ft int
.Fn user2netname "char *name" "const uid_t uid" "const char *domain"
.Sh DESCRIPTION
These routines are part of the
.Tn RPC
library. They implement
.Tn DES
Authentication. See
.Xr rpc 3
for further details about
.Tn RPC .
.Pp
The
.Fn authdes_create
is the first of two routines which interface to the
.Tn RPC
secure authentication system, known as
.Tn DES
authentication.
The second is
.Fn authdes_getucred ,
below.
.Pp
Note: the keyserver daemon
.Xr keyserv 8
must be running for the
.Tn DES
authentication system to work.
.Pp
The
.Fn authdes_create
function,
used on the client side, returns an authentication handle that
will enable the use of the secure authentication system.
The first argument
.Fa name
is the network name, or
.Fa netname ,
of the owner of the server process.
This field usually
represents a
.Fa hostname
derived from the utility routine
.Fn host2netname ,
but could also represent a user name using
.Fn user2netname .
The second field is window on the validity of
the client credential, given in seconds. A small
window is more secure than a large one, but choosing
too small of a window will increase the frequency of
resynchronizations because of clock drift.
The third
argument
.Fa addr
is optional. If it is
.Dv NULL ,
then the authentication system will assume
that the local clock is always in sync with the server's
clock, and will not attempt resynchronizations.
If an address
is supplied, however, then the system will use the address
for consulting the remote time service whenever
resynchronization
is required.
This argument is usually the
address of the
.Tn RPC
server itself.
The final argument
.Fa ckey
is also optional. If it is
.Dv NULL ,
then the authentication system will
generate a random
.Tn DES
key to be used for the encryption of credentials.
If it is supplied, however, then it will be used instead.
.Pp
The
.Fn authdes_getucred
function,
the second of the two
.Tn DES
authentication routines,
is used on the server side for converting a
.Tn DES
credential, which is
operating system independent, into a
.Ux
credential.
This routine differs from utility routine
.Fn netname2user
in that
.Fn authdes_getucred
pulls its information from a cache, and does not have to do a
Yellow Pages lookup every time it is called to get its information.
.Pp
The
.Fn getnetname
function
installs the unique, operating-system independent netname of
the
caller in the fixed-length array
.Fa name .
Returns
.Dv TRUE
if it succeeds and
.Dv FALSE
if it fails.
.Pp
The
.Fn host2netname
function
converts from a domain-specific hostname to an
operating-system independent netname.
Returns
.Dv TRUE
if it succeeds and
.Dv FALSE
if it fails.
Inverse of
.Fn netname2host .
.Pp
The
.Fn key_decryptsession
function
is an interface to the keyserver daemon, which is associated
with
.Tn RPC Ns 's
secure authentication system
.Tn ( DES
authentication).
User programs rarely need to call it, or its associated routines
.Fn key_encryptsession ,
.Fn key_gendes
and
.Fn key_setsecret .
System commands such as
.Xr login 1
and the
.Tn RPC
library are the main clients of these four routines.
.Pp
The
.Fn key_decryptsession
function
takes a server netname and a
.Tn DES
key, and decrypts the key by
using the public key of the server and the secret key
associated with the effective uid of the calling process. It
is the inverse of
.Fn key_encryptsession .
.Pp
The
.Fn key_encryptsession
function
is a keyserver interface routine.
It
takes a server netname and a des key, and encrypts
it using the public key of the server and the secret key
associated with the effective uid of the calling process. It
is the inverse of
.Fn key_decryptsession .
.Pp
The
.Fn key_gendes
function
is a keyserver interface routine.
It
is used to ask the keyserver for a secure conversation key.
Choosing one
.Qq random
is usually not good enough,
because
the common ways of choosing random numbers, such as using the
current time, are very easy to guess.
.Pp
The
.Fn key_setsecret
function
is a keyserver interface routine.
It is used to set the key for
the effective
.Fa uid
of the calling process.
.Pp
The
.Fn netname2host
function
converts from an operating-system independent netname to a
domain-specific hostname.
Returns
.Dv TRUE
if it succeeds and
.Dv FALSE
if it fails. Inverse of
.Fn host2netname .
.Pp
The
.Fn netname2user
function
converts from an operating-system independent netname to a
domain-specific user ID.
Returns
.Dv TRUE
if it succeeds and
.Dv FALSE
if it fails.
Inverse of
.Fn user2netname .
.Pp
The
.Fn user2netname
function
converts from a domain-specific username to an operating-system
independent netname.
Returns
.Dv TRUE
if it succeeds and
.Dv FALSE
if it fails.
Inverse of
.Fn netname2user .
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr xdr 3 ,
.Xr keyserv 8
.Pp
The following manuals:
.Rs
.%B Remote Procedure Calls: Protocol Specification
.Re
.Rs
.%B Remote Procedure Call Programming Guide
.Re
.Rs
.%B Rpcgen Programming Guide
.Re
.Rs
.%B RPC: Remote Procedure Call Protocol Specification
.%O RFC1050, Sun Microsystems Inc., USC-ISI
.Re

1726
libtirpc/man/rpc_soc.3t Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,267 @@
.\" @(#)rpc_svc_calls.3n 1.28 93/05/10 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_svc_calls 1.5 89/07/25 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $NetBSD: rpc_svc_calls.3,v 1.1 2000/06/02 23:11:13 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_calls.3,v 1.8 2003/09/08 19:57:15 ru Exp $
.Dd May 3, 1993
.Dt RPC_SVC_CALLS 3
.Os
.Sh NAME
.Nm svc_dg_enablecache ,
.Nm svc_exit ,
.Nm svc_fdset ,
.Nm svc_freeargs ,
.Nm svc_getargs ,
.Nm svc_getreq_common ,
.Nm svc_getreq_poll ,
.Nm svc_getreqset ,
.Nm svc_getrpccaller ,
.Nm svc_pollset ,
.Nm svc_run ,
.Nm svc_sendreply
.Nd library routines for RPC servers
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft int
.Fn svc_dg_enablecache "SVCXPRT *xprt" "const unsigned cache_size"
.Ft void
.Fn svc_exit "void"
.Ft bool_t
.Fn svc_freeargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
.Ft bool_t
.Fn svc_getargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
.Ft void
.Fn svc_getreq_common "const int fd"
.Ft void
.Fn svc_getreq_poll "struct pollfd *pfdp" "const int pollretval"
.Ft void
.Fn svc_getreqset "fd_set * rdfds"
.Ft "struct netbuf *"
.Fn svc_getrpccaller "const SVCXPRT *xprt"
.Ft "struct cmsgcred *"
.Fn __svc_getcallercreds "const SVCXPRT *xprt"
.Vt struct pollfd svc_pollset[FD_SETSIZE];
.Ft void
.Fn svc_run "void"
.Ft bool_t
.Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "char *out"
.Sh DESCRIPTION
These routines are part of the
RPC
library which allows C language programs to make procedure
calls on other machines across the network.
.Pp
These routines are associated with the server side of the
RPC mechanism.
Some of them are called by the server side dispatch function,
while others
(such as
.Fn svc_run )
are called when the server is initiated.
.\" .Pp
.\" In the current implementation, the service transport handle,
.\" .Dv SVCXPRT ,
.\" contains a single data area for decoding arguments and encoding results.
.\" Therefore, this structure cannot be freely shared between threads that call
.\" functions that do this.
.\" Routines on this page that are affected by this
.\" restriction are marked as unsafe for MT applications.
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt SVCXPRT
data structure.
.Bl -tag -width __svc_getcallercreds()
.It Fn svc_dg_enablecache
This function allocates a duplicate request cache for the
service endpoint
.Fa xprt ,
large enough to hold
.Fa cache_size
entries.
Once enabled, there is no way to disable caching.
This routine returns 0 if space necessary for a cache of the given size
was successfully allocated, and 1 otherwise.
.It Fn svc_exit
This function, when called by any of the RPC server procedure or
otherwise, causes
.Fn svc_run
to return.
.Pp
As currently implemented,
.Fn svc_exit
zeroes the
.Va svc_fdset
global variable.
If RPC server activity is to be resumed,
services must be reregistered with the RPC library
either through one of the
.Xr rpc_svc_create 3
functions, or using
.Fn xprt_register .
The
.Fn svc_exit
function
has global scope and ends all RPC server activity.
.It Xo
.Vt fd_set Va svc_fdset
.Xc
A global variable reflecting the
RPC server's read file descriptor bit mask; it is suitable as an argument
to the
.Xr select 2
system call.
This is only of interest
if service implementors do not call
.Fn svc_run ,
but rather do their own asynchronous event processing.
This variable is read-only (do not pass its address to
.Xr select 2 ! ) ,
yet it may change after calls to
.Fn svc_getreqset
or any creation routines.
.It Fn svc_freeargs
A function macro that frees any data allocated by the
RPC/XDR system when it decoded the arguments to a service procedure
using
.Fn svc_getargs .
This routine returns
.Dv TRUE
if the results were successfully
freed, and
.Dv FALSE
otherwise.
.It Fn svc_getargs
A function macro that decodes the arguments of an
RPC request associated with the RPC
service transport handle
.Fa xprt .
The
.Fa in
argument
is the address where the arguments will be placed;
.Fa inproc
is the XDR
routine used to decode the arguments.
This routine returns
.Dv TRUE
if decoding succeeds, and
.Dv FALSE
otherwise.
.It Fn svc_getreq_common
This routine is called to handle a request on the given
file descriptor.
.It Fn svc_getreq_poll
This routine is only of interest if a service implementor
does not call
.Fn svc_run ,
but instead implements custom asynchronous event processing.
It is called when
.Xr poll 2
has determined that an RPC request has arrived on some RPC
file descriptors;
.Fa pollretval
is the return value from
.Xr poll 2
and
.Fa pfdp
is the array of
.Vt pollfd
structures on which the
.Xr poll 2
was done.
It is assumed to be an array large enough to
contain the maximal number of descriptors allowed.
.It Fn svc_getreqset
This routine is only of interest if a service implementor
does not call
.Fn svc_run ,
but instead implements custom asynchronous event processing.
It is called when
.Xr poll 2
has determined that an RPC
request has arrived on some RPC file descriptors;
.Fa rdfds
is the resultant read file descriptor bit mask.
The routine returns when all file descriptors
associated with the value of
.Fa rdfds
have been serviced.
.It Fn svc_getrpccaller
The approved way of getting the network address of the caller
of a procedure associated with the
RPC service transport handle
.Fa xprt .
.It Fn __svc_getcallercreds
.Em Warning :
this macro is specific to
.Fx
and thus not portable.
This macro returns a pointer to a
.Vt cmsgcred
structure, defined in
.In sys/socket.h ,
identifying the calling client.
This only works if the client is
calling the server over an
.Dv AF_LOCAL
socket.
.It Xo
.Vt struct pollfd Va svc_pollset[FD_SETSIZE] ;
.Xc
.Va svc_pollset
is an array of
.Vt pollfd
structures derived from
.Va svc_fdset[] .
It is suitable as an argument to the
.Xr poll 2
system call.
The derivation of
.Va svc_pollset
from
.Va svc_fdset
is made in the current implementation in
.Fn svc_run .
Service implementors who do not call
.Fn svc_run
and who wish to use this array must perform this derivation themselves.
.It Fn svc_run
This routine never returns.
It waits for RPC
requests to arrive, and calls the appropriate service
procedure using
.Fn svc_getreq_poll
when one arrives.
This procedure is usually waiting for the
.Xr poll 2
system call to return.
.It Fn svc_sendreply
Called by an RPC service's dispatch routine to send the results of a
remote procedure call.
The
.Fa xprt
argument
is the request's associated transport handle;
.Fa outproc
is the XDR
routine which is used to encode the results; and
.Fa out
is the address of the results.
This routine returns
.Dv TRUE
if it succeeds,
.Dv FALSE
otherwise.
.El
.Sh SEE ALSO
.Xr poll 2 ,
.Xr select 2 ,
.Xr rpc 3 ,
.Xr rpc_svc_create 3 ,
.Xr rpc_svc_err 3 ,
.Xr rpc_svc_reg 3

View file

@ -0,0 +1,337 @@
.\" @(#)rpc_svc_create.3n 1.26 93/08/26 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_svc_create 1.3 89/06/28 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_create.3,v 1.7 2003/09/08 19:57:15 ru Exp $
.Dd May 3, 1993
.Dt RPC_SVC_CREATE 3
.Os
.Sh NAME
.Nm rpc_svc_create ,
.Nm svc_control ,
.Nm svc_create ,
.Nm svc_destroy ,
.Nm svc_dg_create ,
.Nm svc_fd_create ,
.Nm svc_raw_create ,
.Nm svc_tli_create ,
.Nm svc_tp_create ,
.Nm svc_vc_create
.Nd library routines for the creation of server handles
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft bool_t
.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info"
.Ft int
.Fn svc_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
.Ft SVCXPRT *
.Fn svc_dg_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
.Ft void
.Fn svc_destroy "SVCXPRT *xprt"
.Ft "SVCXPRT *"
.Fn svc_fd_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
.Ft "SVCXPRT *"
.Fn svc_raw_create "void"
.Ft "SVCXPRT *"
.Fn svc_tli_create "const int fildes" "const struct netconfig *netconf" "const struct t_bind *bindaddr" "const u_int sendsz" "const u_int recvsz"
.Ft "SVCXPRT *"
.Fn svc_tp_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
.Ft "SVCXPRT *"
.Fn svc_vc_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
.Sh DESCRIPTION
These routines are part of the RPC
library which allows C language programs to make procedure
calls on servers across the network.
These routines deal with the creation of service handles.
Once the handle is created, the server can be invoked by calling
.Fn svc_run .
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt SVCXPRT
data structure.
.Bl -tag -width XXXXX
.It Fn svc_control
A function to change or retrieve various information
about a service object.
The
.Fa req
argument
indicates the type of operation and
.Fa info
is a pointer to the information.
The supported values of
.Fa req ,
their argument types, and what they do are:
.Bl -tag -width SVCGET_XID
.It Dv SVCGET_VERSQUIET
If a request is received for a program number
served by this server but the version number
is outside the range registered with the server,
an
.Dv RPC_PROGVERSMISMATCH
error will normally
be returned.
The
.Fa info
argument
should be a pointer to an
integer.
Upon successful completion of the
.Dv SVCGET_VERSQUIET
request,
.Fa *info
contains an
integer which describes the server's current
behavior: 0 indicates normal server behavior
(that is, an
.Dv RPC_PROGVERSMISMATCH
error
will be returned); 1 indicates that the out of
range request will be silently ignored.
.It Dv SVCSET_VERSQUIET
If a request is received for a program number
served by this server but the version number
is outside the range registered with the server,
an
.Dv RPC_PROGVERSMISMATCH
error will normally
be returned.
It is sometimes desirable to
change this behavior.
The
.Fa info
argument
should be a
pointer to an integer which is either 0
(indicating normal server behavior - an
.Dv RPC_PROGVERSMISMATCH
error will be returned),
or 1 (indicating that the out of range request
should be silently ignored).
.El
.It Fn svc_create
The
.Fn svc_create
function
creates server handles for all the transports
belonging to the class
.Fa nettype .
The
.Fa nettype
argument
defines a class of transports which can be used
for a particular application.
The transports are tried in left to right order in
.Ev NETPATH
variable or in top to bottom order in the netconfig database.
If
.Fa nettype
is
.Dv NULL ,
it defaults to
.Qq netpath .
.Pp
The
.Fn svc_create
function
registers itself with the rpcbind
service (see
.Xr rpcbind 8 ) .
The
.Fa dispatch
function
is called when there is a remote procedure call for the given
.Fa prognum
and
.Fa versnum ;
this requires calling
.Fn svc_run
(see
.Fn svc_run
in
.Xr rpc_svc_reg 3 ) .
If
.Fn svc_create
succeeds, it returns the number of server
handles it created,
otherwise it returns 0 and an error message is logged.
.It Fn svc_destroy
A function macro that destroys the RPC
service handle
.Fa xprt .
Destruction usually involves deallocation
of private data structures,
including
.Fa xprt
itself.
Use of
.Fa xprt
is undefined after calling this routine.
.It Fn svc_dg_create
This routine creates a connectionless RPC
service handle, and returns a pointer to it.
This routine returns
.Dv NULL
if it fails, and an error message is logged.
The
.Fa sendsz
and
.Fa recvsz
arguments
are arguments used to specify the size of the buffers.
If they are 0, suitable defaults are chosen.
The file descriptor
.Fa fildes
should be open and bound.
The server is not registered with
.Xr rpcbind 8 .
.Pp
Warning:
since connectionless-based RPC
messages can only hold limited amount of encoded data,
this transport cannot be used for procedures
that take large arguments or return huge results.
.It Fn svc_fd_create
This routine creates a service on top of an open and bound file descriptor,
and returns the handle to it.
Typically, this descriptor is a connected file descriptor for a
connection-oriented transport.
The
.Fa sendsz
and
.Fa recvsz
arguments
indicate sizes for the send and receive buffers.
If they are 0, reasonable defaults are chosen.
This routine returns
.Dv NULL
if it fails, and an error message is logged.
.It Fn svc_raw_create
This routine creates an RPC
service handle and returns a pointer to it.
The transport is really a buffer within the process's
address space, so the corresponding RPC
client should live in the same address space;
(see
.Fn clnt_raw_create
in
.Xr rpc_clnt_create 3 ) .
This routine allows simulation of RPC and acquisition of
RPC overheads (such as round trip times),
without any kernel and networking interference.
This routine returns
.Dv NULL
if it fails, and an error message is logged.
.Pp
Note:
.Fn svc_run
should not be called when the raw interface is being used.
.It Fn svc_tli_create
This routine creates an RPC
server handle, and returns a pointer to it.
The
.Fa fildes
argument
is the file descriptor on which the service is listening.
If
.Fa fildes
is
.Dv RPC_ANYFD ,
it opens a file descriptor on the transport specified by
.Fa netconf .
If the file descriptor is unbound and
.Fa bindaddr
is not
.Dv NULL ,
.Fa fildes
is bound to the address specified by
.Fa bindaddr ,
otherwise
.Fa fildes
is bound to a default address chosen by the transport.
.Pp
Note: the
.Vt t_bind
structure comes from the TLI/XTI SysV interface, which
.Nx
does not use.
The structure is defined in
.In rpc/types.h
for compatibility as:
.Bd -literal
struct t_bind {
struct netbuf addr; /* network address, see rpc(3) */
unsigned int qlen; /* queue length (for listen(2)) */
};
.Ed
.Pp
In the case where the default address is chosen,
the number of outstanding connect requests is set to 8
for connection-oriented transports.
The user may specify the size of the send and receive buffers
with the arguments
.Fa sendsz
and
.Fa recvsz ;
values of 0 choose suitable defaults.
This routine returns
.Dv NULL
if it fails,
and an error message is logged.
The server is not registered with the
.Xr rpcbind 8
service.
.It Fn svc_tp_create
The
.Fn svc_tp_create
function
creates a server handle for the network
specified by
.Fa netconf ,
and registers itself with the rpcbind service.
The
.Fa dispatch
function
is called when there is a remote procedure call
for the given
.Fa prognum
and
.Fa versnum ;
this requires calling
.Fn svc_run .
The
.Fn svc_tp_create
function
returns the service handle if it succeeds,
otherwise a
.Dv NULL
is returned and an error message is logged.
.It Fn svc_vc_create
This routine creates a connection-oriented RPC
service and returns a pointer to it.
This routine returns
.Dv NULL
if it fails, and an error message is logged.
The users may specify the size of the send and receive buffers
with the arguments
.Fa sendsz
and
.Fa recvsz ;
values of 0 choose suitable defaults.
The file descriptor
.Fa fildes
should be open and bound.
The server is not registered with the
.Xr rpcbind 8
service.
.El
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr rpc_svc_calls 3 ,
.Xr rpc_svc_err 3 ,
.Xr rpc_svc_reg 3 ,
.Xr rpcbind 8

View file

@ -0,0 +1,97 @@
.\" @(#)rpc_svc_err.3n 1.23 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_svc_err 1.4 89/06/28 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $NetBSD: rpc_svc_err.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_err.3,v 1.4 2002/12/19 09:40:23 ru Exp $
.Dd May 3, 1993
.Dt RPC_SVC_ERR 3
.Os
.Sh NAME
.Nm rpc_svc_err ,
.Nm svcerr_auth ,
.Nm svcerr_decode ,
.Nm svcerr_noproc ,
.Nm svcerr_noprog ,
.Nm svcerr_progvers ,
.Nm svcerr_systemerr ,
.Nm svcerr_weakauth
.Nd library routines for server side remote procedure call errors
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft void
.Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why"
.Ft void
.Fn svcerr_decode "SVCXPRT *xprt"
.Ft void
.Fn svcerr_noproc "SVCXPRT *xprt"
.Ft void
.Fn svcerr_noprog "SVCXPRT *xprt"
.Ft void
.Fn svcerr_progvers "SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers"
.Ft void
.Fn svcerr_systemerr "SVCXPRT *xprt"
.Ft void
.Fn svcerr_weakauth "SVCXPRT *xprt"
.Sh DESCRIPTION
These routines are part of the RPC
library which allows C language programs to make procedure
calls on other machines across the network.
.Pp
These routines can be called by the server side
dispatch function if there is any error in the
transaction with the client.
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt SVCXPRT
data structure.
.Bl -tag -width XXXXX
.It Fn svcerr_auth
Called by a service dispatch routine that refuses to perform
a remote procedure call due to an authentication error.
.It Fn svcerr_decode
Called by a service dispatch routine that cannot successfully
decode the remote arguments
(see
.Fn svc_getargs
in
.Xr rpc_svc_reg 3 ) .
.It Fn svcerr_noproc
Called by a service dispatch routine that does not implement
the procedure number that the caller requests.
.It Fn svcerr_noprog
Called when the desired program is not registered with the
RPC package.
Service implementors usually do not need this routine.
.It Fn svcerr_progvers
Called when the desired version of a program is not registered with the
RPC package.
The
.Fa low_vers
argument
is the lowest version number,
and
.Fa high_vers
is the highest version number.
Service implementors usually do not need this routine.
.It Fn svcerr_systemerr
Called by a service dispatch routine when it detects a system
error not covered by any particular protocol.
For example, if a service can no longer allocate storage,
it may call this routine.
.It Fn svcerr_weakauth
Called by a service dispatch routine that refuses to perform
a remote procedure call due to insufficient (but correct)
authentication arguments.
The routine calls
.Fn svcerr_auth "xprt" "AUTH_TOOWEAK" .
.El
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr rpc_svc_calls 3 ,
.Xr rpc_svc_create 3 ,
.Xr rpc_svc_reg 3

183
libtirpc/man/rpc_svc_reg.3t Normal file
View file

@ -0,0 +1,183 @@
.\" @(#)rpc_svc_reg.3n 1.32 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_svc_call 1.6 89/07/20 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $NetBSD: rpc_svc_reg.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_reg.3,v 1.5 2002/12/19 09:40:23 ru Exp $
.Dd May 3, 1993
.Dt RPC_SVC_REG 3
.Os
.Sh NAME
.Nm rpc_svc_reg ,
.Nm rpc_reg ,
.Nm svc_reg ,
.Nm svc_unreg ,
.Nm svc_auth_reg ,
.Nm xprt_register ,
.Nm xprt_unregister
.Nd library routines for registering servers
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft int
.Fn rpc_reg "rpcprog_t prognum" "rpcvers_t versnum" "rpcproc_t procnum" "char *(*procname)()" "xdrproc_t inproc" "xdrproc_t outproc" "char *nettype"
.Ft bool_t
.Fn svc_reg "SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const struct netconfig *netconf"
.Ft void
.Fn svc_unreg "const rpcprog_t prognum" "const rpcvers_t versnum"
.Ft int
.Fn svc_auth_reg "int cred_flavor" "enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)"
.Ft void
.Fn xprt_register "SVCXPRT *xprt"
.Ft void
.Fn xprt_unregister "SVCXPRT *xprt"
.Sh DESCRIPTION
These routines are a part of the RPC
library which allows the RPC
servers to register themselves with rpcbind
(see
.Xr rpcbind 8 ) ,
and associate the given program and version
number with the dispatch function.
When the RPC server receives a RPC request, the library invokes the
dispatch routine with the appropriate arguments.
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt SVCXPRT
data structure.
.Bl -tag -width XXXXX
.It Fn rpc_reg
Register program
.Fa prognum ,
procedure
.Fa procname ,
and version
.Fa versnum
with the RPC
service package.
If a request arrives for program
.Fa prognum ,
version
.Fa versnum ,
and procedure
.Fa procnum ,
.Fa procname
is called with a pointer to its argument(s);
.Fa procname
should return a pointer to its static result(s);
.Fa inproc
is the XDR function used to decode the arguments while
.Fa outproc
is the XDR function used to encode the results.
Procedures are registered on all available transports of the class
.Fa nettype .
See
.Xr rpc 3 .
This routine returns 0 if the registration succeeded,
\-1 otherwise.
.It Fn svc_reg
Associates
.Fa prognum
and
.Fa versnum
with the service dispatch procedure,
.Fa dispatch .
If
.Fa netconf
is
.Dv NULL ,
the service is not registered with the
.Xr rpcbind 8
service.
If
.Fa netconf
is non-zero,
then a mapping of the triple
.Bq Fa prognum , versnum , netconf->nc_netid
to
.Fa xprt->xp_ltaddr
is established with the local rpcbind
service.
.Pp
The
.Fn svc_reg
routine returns 1 if it succeeds,
and 0 otherwise.
.It Fn svc_unreg
Remove from the rpcbind
service, all mappings of the triple
.Bq Fa prognum , versnum , No all-transports
to network address
and all mappings within the RPC service package
of the double
.Bq Fa prognum , versnum
to dispatch routines.
.It Fn svc_auth_reg
Registers the service authentication routine
.Fa handler
with the dispatch mechanism so that it can be
invoked to authenticate RPC requests received
with authentication type
.Fa cred_flavor .
This interface allows developers to add new authentication
types to their RPC applications without needing to modify
the libraries.
Service implementors usually do not need this routine.
.Pp
Typical service application would call
.Fn svc_auth_reg
after registering the service and prior to calling
.Fn svc_run .
When needed to process an RPC credential of type
.Fa cred_flavor ,
the
.Fa handler
procedure will be called with two arguments,
.Fa "struct svc_req *rqst"
and
.Fa "struct rpc_msg *msg" ,
and is expected to return a valid
.Vt "enum auth_stat"
value.
There is no provision to change or delete an authentication handler
once registered.
.Pp
The
.Fn svc_auth_reg
routine returns 0 if the registration is successful,
1 if
.Fa cred_flavor
already has an authentication handler registered for it,
and \-1 otherwise.
.It Fn xprt_register
After RPC service transport handle
.Fa xprt
is created, it is registered with the RPC
service package.
This routine modifies the global variable
.Va svc_fdset
(see
.Xr rpc_svc_calls 3 ) .
Service implementors usually do not need this routine.
.It Fn xprt_unregister
Before an RPC service transport handle
.Fa xprt
is destroyed, it unregisters itself with the
RPC service package.
This routine modifies the global variable
.Va svc_fdset
(see
.Xr rpc_svc_calls 3 ) .
Service implementors usually do not need this routine.
.El
.Sh SEE ALSO
.Xr select 2 ,
.Xr rpc 3 ,
.Xr rpcbind 3 ,
.Xr rpc_svc_calls 3 ,
.Xr rpc_svc_create 3 ,
.Xr rpc_svc_err 3 ,
.Xr rpcbind 8

101
libtirpc/man/rpc_xdr.3t Normal file
View file

@ -0,0 +1,101 @@
.\" @(#)rpc_xdr.3n 1.24 93/08/31 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" @(#)rpc_xdr.new 1.1 89/04/06 SMI;
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
.\" $FreeBSD: src/lib/libc/rpc/rpc_xdr.3,v 1.3 2001/10/03 16:47:56 bde Exp $
.Dd May 3, 1993
.Dt RPC_XDR 3
.Os
.Sh NAME
.Nm xdr_accepted_reply ,
.Nm xdr_authsys_parms ,
.Nm xdr_callhdr ,
.Nm xdr_callmsg ,
.Nm xdr_opaque_auth ,
.Nm xdr_rejected_reply ,
.Nm xdr_replymsg
.Nd XDR library routines for remote procedure calls
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft bool_t
.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar"
.Ft bool_t
.Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp"
.Ft bool_t
.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr"
.Ft bool_t
.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg"
.Ft bool_t
.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap"
.Ft bool_t
.Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr"
.Ft bool_t
.Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg"
.Sh DESCRIPTION
These routines are used for describing the
RPC messages in XDR language.
They should normally be used by those who do not
want to use the RPC
package directly.
These routines return
.Dv TRUE
if they succeed,
.Dv FALSE
otherwise.
.Sh Routines
See
.Xr rpc 3
for the definition of the
.Vt XDR
data structure.
.Bl -tag -width XXXXX
.It Fn xdr_accepted_reply
Used to translate between RPC
reply messages and their external representation.
It includes the status of the RPC
call in the XDR language format.
In the case of success, it also includes the call results.
.It Fn xdr_authsys_parms
Used for describing
.Ux
operating system credentials.
It includes machine-name, uid, gid list, etc.
.It Fn xdr_callhdr
Used for describing
RPC
call header messages.
It encodes the static part of the call message header in the
XDR language format.
It includes information such as transaction
ID, RPC version number, program and version number.
.It Fn xdr_callmsg
Used for describing
RPC call messages.
This includes all the RPC
call information such as transaction
ID, RPC version number, program number, version number,
authentication information, etc.
This is normally used by servers to determine information about the client
RPC call.
.It Fn xdr_opaque_auth
Used for describing RPC
opaque authentication information messages.
.It Fn xdr_rejected_reply
Used for describing RPC reply messages.
It encodes the rejected RPC message in the XDR language format.
The message could be rejected either because of version
number mis-match or because of authentication errors.
.It Fn xdr_replymsg
Used for describing RPC
reply messages.
It translates between the
RPC reply message and its external representation.
This reply could be either an acceptance,
rejection or
.Dv NULL .
.El
.Sh SEE ALSO
.Xr rpc 3 ,
.Xr xdr 3

194
libtirpc/man/rpcbind.3t Normal file
View file

@ -0,0 +1,194 @@
.\" @(#)rpcbind.3n 1.25 93/05/07 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" Copyright (c) 1988 Sun Microsystem's, Inc. - All Right's Reserved.
.\" $NetBSD: rpcbind.3,v 1.2 2000/06/03 18:47:28 fvdl Exp $
.\" $FreeBSD: src/lib/libc/rpc/rpcbind.3,v 1.5 2002/12/19 09:40:23 ru Exp $
.Dd May 7, 1993
.Dt RPCBIND 3
.Os
.Sh NAME
.Nm rpcb_getmaps ,
.Nm rpcb_getaddr ,
.Nm rpcb_gettime ,
.Nm rpcb_rmtcall ,
.Nm rpcb_set ,
.Nm rpcb_unset
.Nd library routines for RPC bind service
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In rpc/rpc.h
.Ft "rpcblist *"
.Fn rpcb_getmaps "const struct netconfig *netconf" "const char *host"
.Ft bool_t
.Fn rpcb_getaddr "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const char *host"
.Ft bool_t
.Fn rpcb_gettime "const char *host" "time_t * timep"
.Ft "enum clnt_stat"
.Fn rpcb_rmtcall "const struct netconfig *netconf" "const char *host" "const rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "const caddr_t out" "const struct timeval tout, const struct netbuf *svcaddr"
.Ft bool_t
.Fn rpcb_set "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct netbuf *svcaddr"
.Ft bool_t
.Fn rpcb_unset "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
.Sh DESCRIPTION
These routines allow client C programs to make procedure
calls to the RPC binder service.
(see
.Xr rpcbind 8 )
maintains a list of mappings between programs
and their universal addresses.
.Sh Routines
.Bl -tag -width XXXXX
.It Fn rpcb_getmaps
An interface to the rpcbind service,
which returns a list of the current
RPC program-to-address mappings on
.Fa host .
It uses the transport specified through
.Fa netconf
to contact the remote rpcbind
service on
.Fa host .
This routine will return
.Dv NULL ,
if the remote rpcbind could not be contacted.
.It Fn rpcb_getaddr
An interface to the rpcbind
service, which finds the address of the service on
.Fa host
that is registered with program number
.Fa prognum ,
version
.Fa versnum ,
and speaks the transport protocol associated with
.Fa netconf .
The address found is returned in
.Fa svcaddr .
The
.Fa svcaddr
argument
should be preallocated.
This routine returns
.Dv TRUE
if it succeeds.
A return value of
.Dv FALSE
means that the mapping does not exist
or that the RPC
system failed to contact the remote
rpcbind service.
In the latter case, the global variable
.Va rpc_createerr
(see
.Xr rpc_clnt_create 3 )
contains the
RPC status.
.It Fn rpcb_gettime
This routine returns the time on
.Fa host
in
.Fa timep .
If
.Fa host
is
.Dv NULL ,
.Fn rpcb_gettime
returns the time on its own machine.
This routine returns
.Dv TRUE
if it succeeds,
.Dv FALSE
if it fails.
The
.Fn rpcb_gettime
function
can be used to synchronize the time between the
client and the remote server.
.It Fn rpcb_rmtcall
An interface to the rpcbind service, which instructs
rpcbind on
.Fa host
to make an RPC
call on your behalf to a procedure on that host.
The
.Fn netconfig
structure should correspond to a connectionless transport.
The
.Fa svcaddr
argument
will be modified to the server's address if the procedure succeeds
(see
.Fn rpc_call
and
.Fn clnt_call
in
.Xr rpc_clnt_calls 3
for the definitions of other arguments).
.Pp
This procedure should normally be used for a
.Dq ping
and nothing else.
This routine allows programs to do lookup and call, all in one step.
.Pp
Note: Even if the server is not running
.Fn rpcb_rmtcall
does not return any error messages to the caller.
In such a case, the caller times out.
.Pp
Note:
.Fn rpcb_rmtcall
is only available for connectionless transports.
.It Fn rpcb_set
An interface to the rpcbind
service, which establishes a mapping between the triple
.Bq Fa prognum , versnum , netconf->nc_netid
and
.Fa svcaddr
on the machine's rpcbind
service.
The value of
.Fa nc_netid
must correspond to a network identifier that is defined by the
netconfig database.
This routine returns
.Dv TRUE
if it succeeds,
.Dv FALSE
otherwise.
(See also
.Fn svc_reg
in
.Xr rpc_svc_calls 3 . )
If there already exists such an entry with rpcbind,
.Fn rpcb_set
will fail.
.It Fn rpcb_unset
An interface to the rpcbind
service, which destroys the mapping between the triple
.Bq Fa prognum , versnum , netconf->nc_netid
and the address on the machine's rpcbind
service.
If
.Fa netconf
is
.Dv NULL ,
.Fn rpcb_unset
destroys all mapping between the triple
.Bq Fa prognum , versnum , No all-transports
and the addresses on the machine's rpcbind service.
This routine returns
.Dv TRUE
if it succeeds,
.Dv FALSE
otherwise.
Only the owner of the service or the super-user can destroy the mapping.
(See also
.Fn svc_unreg
in
.Xr rpc_svc_calls 3 . )
.El
.Sh SEE ALSO
.Xr rpc_clnt_calls 3 ,
.Xr rpc_svc_calls 3 ,
.Xr rpcbind 8 ,
.Xr rpcinfo 8

50
libtirpc/man/rtime.3t Normal file
View file

@ -0,0 +1,50 @@
.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI
.\" $FreeBSD: src/lib/libc/rpc/rtime.3,v 1.8 2002/12/19 09:40:23 ru Exp $
.\"
.Dd November 22, 1987
.Dt RTIME 3
.Os
.Sh NAME
.Nm rtime
.Nd "get remote time"
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In sys/time.h
.In netinet/in.h
.Ft int
.Fo rtime
.Fa "struct sockaddr_in *addrp"
.Fa "struct timeval *timep"
.Fa "struct timeval *timeout"
.Fc
.Sh DESCRIPTION
The
.Fn rtime
function
consults the Internet Time Server at the address pointed to by
.Fa addrp
and returns the remote time in the
.Vt timeval
struct pointed to by
.Fa timep .
Normally, the
.Tn UDP
protocol is used when consulting the Time Server.
The
.Fa timeout
argument specifies how long the
routine should wait before giving
up when waiting for a reply.
If
.Fa timeout
is specified as
.Dv NULL ,
however, the routine will instead use
.Tn TCP
and block until a reply is received from the time server.
.Sh RETURN VALUES
.Rv -std rtime
.Sh SEE ALSO
.Xr timed 8

95
libtirpc/src/Makefile.am Normal file
View file

@ -0,0 +1,95 @@
## Process this file with automake to create Makefile.in.
## NOTE: this file doesn't really try to be complete. In particular
## `make dist' won't work at all. We're just aiming to get the
## program built. We also don't bother trying to assemble code, or
## anything like that.
INCLUDES = -I$(top_srcdir)/tirpc -DPORTMAP -DINET6 -DVERSION="\"$(VERSION)\"" \
-D_GNU_SOURCE -Wall -pipe
lib_LTLIBRARIES = libtirpc.la
#
# Set the library version information
#
# According to the libtool manual:
#
# "This flag accepts an argument of the form current[:revision[:age]].
#
# If either revision or age are omitted, they default to 0. Also note that
# age must be less than or equal to the current interface number.
#
# Here are a set of rules to help you update your library version information:
#
# 1. Start with version information of 0:0:0 for each libtool library.
# 2. Update the version information only immediately before a public
# release of your software. More frequent updates are unnecessary,
# and only guarantee that the current interface number gets larger faster.
# 3. If the library source code has changed at all since the last update,
# then increment revision (c:r:a becomes c:r+1:a).
# 4. If any interfaces have been added, removed, or changed since the last
# update, increment current, and set revision to 0.
# 5. If any interfaces have been added since the last public release,
# then increment age.
# 6. If any interfaces have been removed since the last public release,
# then set age to 0.
#
# _Never_ try to set the interface numbers so that they correspond to the
# release number of your package. This is an abuse that only fosters
# misunderstanding of the purpose of library versions."
#
libtirpc_la_LDFLAGS = -lnsl -lpthread -version-info 1:10:0
libtirpc_la_SOURCES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \
getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \
rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c \
svc_raw.c svc_run.c svc_simple.c svc_vc.c getpeereid.c \
auth_time.c auth_des.c authdes_prot.c
## XDR
libtirpc_la_SOURCES += xdr.c xdr_rec.c xdr_array.c xdr_float.c xdr_mem.c xdr_reference.c xdr_stdio.c
## Secure-RPC
if GSS
libtirpc_la_SOURCES += auth_gss.c authgss_prot.c svc_auth_gss.c \
svc_auth_none.c
libtirpc_la_LDFLAGS += $(GSSGLUE_LIBS)
libtirpc_la_CFLAGS = -DHAVE_RPCSEC_GSS $(GSSGLUE_CFLAGS)
endif
## libtirpc_a_SOURCES += key_call.c key_prot_xdr.c getpublickey.c
## libtirpc_a_SOURCES += netname.c netnamer.c rpcdname.c \
## libtirpc_a_SOURCES += rtime.c \
## auth_time.c auth_des.c authdes_prot.c
if GSS
$(libtirpc_la_OBJECTS) :auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \
getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \
rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c \
svc_raw.c svc_run.c svc_simple.c svc_vc.c \
xdr.c xdr_rec.c xdr_array.c xdr_float.c xdr_mem.c xdr_reference.c xdr_stdio.c \
auth_gss.c authgss_prot.c svc_auth_gss.c getpeereid.c \
auth_time.c auth_des.c authdes_prot.c svc_auth_none.c
else
$(libtirpc_la_OBJECTS) :auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \
getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \
rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c \
svc_raw.c svc_run.c svc_simple.c svc_vc.c \
xdr.c xdr_rec.c xdr_array.c xdr_float.c xdr_mem.c xdr_reference.c xdr_stdio.c \
getpeereid.c auth_time.c auth_des.c authdes_prot.c
endif

105
libtirpc/src/asprintf.c Normal file
View file

@ -0,0 +1,105 @@
/* Copyright (c) 2004 Darren Tucker.
*
* Based originally on asprintf.c from OpenBSD:
* Copyright (c) 1997 Todd C. Miller <Todd.Miller AT courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//extern int vsnprintf();
#include <wintirpc.h>
#include <stdio.h>
#include <varargs.h>
/* Include vasprintf() if not on your OS. */
#ifndef HAVE_VASPRINTF
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef VA_COPY
# ifdef HAVE_VA_COPY
# define VA_COPY(dest, src) va_copy(dest, src)
# else
# ifdef HAVE___VA_COPY
# define VA_COPY(dest, src) __va_copy(dest, src)
# else
# define VA_COPY(dest, src) (dest) = (src)
# endif
# endif
#endif
#define INIT_SZ 128
int
vasprintf(char **str, const char *fmt, va_list ap)
{
int ret = -1;
va_list ap2;
char *string, *newstr;
size_t len;
VA_COPY(ap2, ap);
if ((string = malloc(INIT_SZ)) == NULL)
goto fail;
ret = _vsnprintf(string, INIT_SZ, fmt, ap2);
if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
*str = string;
} else if (ret == INT_MAX || ret < 0) { /* Bad length */
goto fail;
} else { /* bigger than initial, realloc allowing for nul */
len = (size_t)ret + 1;
if ((newstr = realloc(string, len)) == NULL) {
free(string);
goto fail;
} else {
va_end(ap2);
VA_COPY(ap2, ap);
ret = _vsnprintf(newstr, len, fmt, ap2);
if (ret >= 0 && (size_t)ret < len) {
*str = newstr;
} else { /* failed with realloc'ed string, give up */
free(newstr);
goto fail;
}
}
}
va_end(ap2);
return (ret);
fail:
*str = NULL;
errno = ENOMEM;
va_end(ap2);
return (-1);
}
#endif
/* Include asprintf() if not on your OS. */
#ifndef HAVE_ASPRINTF
int asprintf(char **str, const char *fmt, ...)
{
va_list ap;
int ret;
*str = NULL;
va_start(ap, fmt);
ret = vasprintf(str, fmt, ap);
va_end(ap);
return ret;
}
#endif

499
libtirpc/src/auth_des.c Normal file
View file

@ -0,0 +1,499 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* auth_des.c, client-side implementation of DES authentication
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
//#include <err.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
//#include <unistd.h>
//#include <sys/cdefs.h>
#include <rpc/des_crypt.h>
//#include <syslog.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/auth_des.h>
#include <rpc/clnt.h>
#include <rpc/xdr.h>
//#include <sys/socket.h>
#undef NIS
#include <rpcsvc/nis.h>
#if defined(LIBC_SCCS) && !defined(lint)
#endif
//#include <sys/cdefs.h>
#define USEC_PER_SEC 1000000
#define RTIME_TIMEOUT 5 /* seconds to wait for sync */
#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private
#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type))
#define FREE(ptr, size) mem_free((char *)(ptr), (int) size)
#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
extern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *);
extern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *);
extern int key_encryptsession_pk();
extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
char **, char **);
/*
* DES authenticator operations vector
*/
static void authdes_nextverf(AUTH *);
static bool_t authdes_marshal(AUTH *, XDR *);
static bool_t authdes_validate(AUTH *, struct opaque_auth *);
static bool_t authdes_refresh(AUTH *, void *);
static void authdes_destroy(AUTH *);
static struct auth_ops *authdes_ops(void);
/*
* This struct is pointed to by the ah_private field of an "AUTH *"
*/
struct ad_private {
char *ad_fullname; /* client's full name */
u_int ad_fullnamelen; /* length of name, rounded up */
char *ad_servername; /* server's full name */
u_int ad_servernamelen; /* length of name, rounded up */
u_int ad_window; /* client specified window */
bool_t ad_dosync; /* synchronize? */
struct netbuf ad_syncaddr; /* remote host to synch with */
char *ad_timehost; /* remote host to synch with */
struct timeval ad_timediff; /* server's time - client's time */
u_int ad_nickname; /* server's nickname for client */
struct authdes_cred ad_cred; /* storage for credential */
struct authdes_verf ad_verf; /* storage for verifier */
struct timeval ad_timestamp; /* timestamp sent */
des_block ad_xkey; /* encrypted conversation key */
u_char ad_pkey[1024]; /* Server's actual public key */
char *ad_netid; /* Timehost netid */
char *ad_uaddr; /* Timehost uaddr */
nis_server *ad_nis_srvr; /* NIS+ server struct */
};
AUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *,
const des_block *, nis_server *);
/*
* documented version of authdes_seccreate
*/
/*
servername: network name of server
win: time to live
timehost: optional hostname to sync with
ckey: optional conversation key to use
*/
AUTH *
authdes_seccreate(const char *servername, const u_int win,
const char *timehost, const des_block *ckey)
{
u_char pkey_data[1024];
netobj pkey;
AUTH *dummy;
if (! getpublickey(servername, (char *) pkey_data)) {
//syslog(LOG_ERR,
// "authdes_seccreate: no public key found for %s",
// servername);
return (NULL);
}
pkey.n_bytes = (char *) pkey_data;
pkey.n_len = (u_int)strlen((char *)pkey_data) + 1;
dummy = authdes_pk_seccreate(servername, &pkey, win, timehost,
ckey, NULL);
return (dummy);
}
/*
* Slightly modified version of authdessec_create which takes the public key
* of the server principal as an argument. This spares us a call to
* getpublickey() which in the nameserver context can cause a deadlock.
*/
AUTH *
authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window,
const char *timehost, const des_block *ckey, nis_server *srvr)
{
AUTH *auth;
struct ad_private *ad;
char namebuf[MAXNETNAMELEN+1];
/*
* Allocate everything now
*/
auth = ALLOC(AUTH);
if (auth == NULL) {
//syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
return (NULL);
}
ad = ALLOC(struct ad_private);
if (ad == NULL) {
//syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
goto failed;
}
ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
ad->ad_timehost = NULL;
ad->ad_netid = NULL;
ad->ad_uaddr = NULL;
ad->ad_nis_srvr = NULL;
ad->ad_timediff.tv_sec = 0;
ad->ad_timediff.tv_usec = 0;
memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
if (!getnetname(namebuf))
goto failed;
ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
ad->ad_servernamelen = strlen(servername);
ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
//syslog(LOG_ERR, "authdes_seccreate: out of memory");
goto failed;
}
if (timehost != NULL) {
ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
if (ad->ad_timehost == NULL) {
//syslog(LOG_ERR, "authdes_seccreate: out of memory");
goto failed;
}
memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
ad->ad_dosync = TRUE;
} else if (srvr != NULL) {
ad->ad_nis_srvr = srvr; /* transient */
ad->ad_dosync = TRUE;
} else {
ad->ad_dosync = FALSE;
}
memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
ad->ad_window = window;
if (ckey == NULL) {
if (key_gendes(&auth->ah_key) < 0) {
//syslog(LOG_ERR,
// "authdes_seccreate: keyserv(1m) is unable to generate session key");
goto failed;
}
} else {
auth->ah_key = *ckey;
}
/*
* Set up auth handle
*/
auth->ah_cred.oa_flavor = AUTH_DES;
auth->ah_verf.oa_flavor = AUTH_DES;
auth->ah_ops = authdes_ops();
auth->ah_private = (caddr_t)ad;
if (!authdes_refresh(auth, NULL)) {
goto failed;
}
ad->ad_nis_srvr = NULL; /* not needed any longer */
return (auth);
failed:
if (auth)
FREE(auth, sizeof (AUTH));
if (ad) {
if (ad->ad_fullname)
FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
if (ad->ad_servername)
FREE(ad->ad_servername, ad->ad_servernamelen + 1);
if (ad->ad_timehost)
FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
if (ad->ad_netid)
FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
if (ad->ad_uaddr)
FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
FREE(ad, sizeof (struct ad_private));
}
return (NULL);
}
/*
* Implement the five authentication operations
*/
/*
* 1. Next Verifier
*/
/*ARGSUSED*/
static void
authdes_nextverf(AUTH *auth)
{
/* what the heck am I supposed to do??? */
}
/*
* 2. Marshal
*/
static bool_t
authdes_marshal(AUTH *auth, XDR *xdrs)
{
/* LINTED pointer alignment */
struct ad_private *ad = AUTH_PRIVATE(auth);
struct authdes_cred *cred = &ad->ad_cred;
struct authdes_verf *verf = &ad->ad_verf;
des_block cryptbuf[2];
des_block ivec;
int status;
int len;
rpc_inline_t *ixdr;
/*
* Figure out the "time", accounting for any time difference
* with the server if necessary.
*/
(void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
ad->ad_timestamp.tv_sec++;
}
/*
* XDR the timestamp and possibly some other things, then
* encrypt them.
*/
ixdr = (rpc_inline_t *)cryptbuf;
IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
IXDR_PUT_U_INT32(ixdr, ad->ad_window);
IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
ivec.key.high = ivec.key.low = 0;
status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
(u_int) 2 * sizeof (des_block),
DES_ENCRYPT | DES_HW, (char *)&ivec);
} else {
status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
(u_int) sizeof (des_block),
DES_ENCRYPT | DES_HW);
}
if (DES_FAILED(status)) {
//syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
return (FALSE);
}
ad->ad_verf.adv_xtimestamp = cryptbuf[0];
if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
} else {
ad->ad_cred.adc_nickname = ad->ad_nickname;
ad->ad_verf.adv_winverf = 0;
}
/*
* Serialize the credential and verifier into opaque
* authentication data.
*/
if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
} else {
len = (1 + 1)*BYTES_PER_XDR_UNIT;
}
if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
IXDR_PUT_INT32(ixdr, AUTH_DES);
IXDR_PUT_INT32(ixdr, len);
} else {
ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
ATTEMPT(xdr_putint32(xdrs, &len));
}
ATTEMPT(xdr_authdes_cred(xdrs, cred));
len = (2 + 1)*BYTES_PER_XDR_UNIT;
if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
IXDR_PUT_INT32(ixdr, AUTH_DES);
IXDR_PUT_INT32(ixdr, len);
} else {
ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
ATTEMPT(xdr_putint32(xdrs, &len));
}
ATTEMPT(xdr_authdes_verf(xdrs, verf));
return (TRUE);
}
/*
* 3. Validate
*/
static bool_t
authdes_validate(AUTH *auth, struct opaque_auth *rverf)
{
/* LINTED pointer alignment */
struct ad_private *ad = AUTH_PRIVATE(auth);
struct authdes_verf verf;
int status;
uint32_t *ixdr;
des_block buf;
if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
return (FALSE);
}
/* LINTED pointer alignment */
ixdr = (uint32_t *)rverf->oa_base;
buf.key.high = (uint32_t)*ixdr++;
buf.key.low = (uint32_t)*ixdr++;
verf.adv_int_u = (uint32_t)*ixdr++;
/*
* Decrypt the timestamp
*/
status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
(u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
if (DES_FAILED(status)) {
//syslog(LOG_ERR, "authdes_validate: DES decryption failure");
return (FALSE);
}
/*
* xdr the decrypted timestamp
*/
/* LINTED pointer alignment */
ixdr = (uint32_t *)buf.c;
verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
/*
* validate
*/
if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
sizeof(struct timeval)) != 0) {
//syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
return (FALSE);
}
/*
* We have a nickname now, let's use it
*/
ad->ad_nickname = verf.adv_nickname;
ad->ad_cred.adc_namekind = ADN_NICKNAME;
return (TRUE);
}
/*
* 4. Refresh
*/
/*ARGSUSED*/
static bool_t
authdes_refresh(AUTH *auth, void *dummy)
{
/* LINTED pointer alignment */
struct ad_private *ad = AUTH_PRIVATE(auth);
struct authdes_cred *cred = &ad->ad_cred;
int ok;
netobj pkey;
if (ad->ad_dosync) {
#if 1 // WINDOWS
ok = 1;
#else
ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
ad->ad_timehost, &(ad->ad_uaddr),
&(ad->ad_netid));
#endif
if (! ok) {
/*
* Hope the clocks are synced!
*/
ad->ad_dosync = 0;
//syslog(LOG_DEBUG,
// "authdes_refresh: unable to synchronize clock");
}
}
ad->ad_xkey = auth->ah_key;
pkey.n_bytes = (char *)(ad->ad_pkey);
pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
//syslog(LOG_INFO,
// "authdes_refresh: keyserv(1m) is unable to encrypt session key");
return (FALSE);
}
cred->adc_fullname.key = ad->ad_xkey;
cred->adc_namekind = ADN_FULLNAME;
cred->adc_fullname.name = ad->ad_fullname;
return (TRUE);
}
/*
* 5. Destroy
*/
static void
authdes_destroy(AUTH *auth)
{
/* LINTED pointer alignment */
struct ad_private *ad = AUTH_PRIVATE(auth);
FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
FREE(ad->ad_servername, ad->ad_servernamelen + 1);
if (ad->ad_timehost)
FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
if (ad->ad_netid)
FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
if (ad->ad_uaddr)
FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
FREE(ad, sizeof (struct ad_private));
FREE(auth, sizeof(AUTH));
}
static struct auth_ops *
authdes_ops(void)
{
static struct auth_ops ops;
extern mutex_t authdes_ops_lock;
/* VARIABLES PROTECTED BY ops_lock: ops */
mutex_lock(&authdes_ops_lock);
if (ops.ah_nextverf == NULL) {
ops.ah_nextverf = authdes_nextverf;
ops.ah_marshal = authdes_marshal;
ops.ah_validate = authdes_validate;
ops.ah_refresh = authdes_refresh;
ops.ah_destroy = authdes_destroy;
}
mutex_unlock(&authdes_ops_lock);
return (&ops);
}

633
libtirpc/src/auth_gss.c Normal file
View file

@ -0,0 +1,633 @@
/*
auth_gss.c
RPCSEC_GSS client routines.
Copyright (c) 2000 The Regents of the University of Michigan.
All rights reserved.
Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
All rights reserved, all wrongs reversed.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_gss.h>
#include <rpc/clnt.h>
#include <netinet/in.h>
#include <gssapi/gssapi.h>
static void authgss_nextverf();
static bool_t authgss_marshal();
static bool_t authgss_refresh();
static bool_t authgss_validate();
static void authgss_destroy();
static void authgss_destroy_context();
static bool_t authgss_wrap();
static bool_t authgss_unwrap();
/*
* from mit-krb5-1.2.1 mechglue/mglueP.h:
* Array of context IDs typed by mechanism OID
*/
typedef struct gss_union_ctx_id_t {
gss_OID mech_type;
gss_ctx_id_t internal_ctx_id;
} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
static struct auth_ops authgss_ops = {
authgss_nextverf,
authgss_marshal,
authgss_validate,
authgss_refresh,
authgss_destroy,
authgss_wrap,
authgss_unwrap
};
#ifdef DEBUG
/* useful as i add more mechanisms */
void
print_rpc_gss_sec(struct rpc_gss_sec *ptr)
{
int i;
char *p;
log_debug("rpc_gss_sec:");
if(ptr->mech == NULL)
log_debug("NULL gss_OID mech");
else {
fprintf(stderr, " mechanism_OID: {");
p = (char *)ptr->mech->elements;
for (i=0; i < ptr->mech->length; i++)
/* First byte of OIDs encoded to save a byte */
if (i == 0) {
int first, second;
if (*p < 40) {
first = 0;
second = *p;
}
else if (40 <= *p && *p < 80) {
first = 1;
second = *p - 40;
}
else if (80 <= *p && *p < 127) {
first = 2;
second = *p - 80;
}
else {
/* Invalid value! */
first = -1;
second = -1;
}
fprintf(stderr, " %u %u", first, second);
p++;
}
else {
fprintf(stderr, " %u", (unsigned char)*p++);
}
fprintf(stderr, " }\n");
}
fprintf(stderr, " qop: %d\n", ptr->qop);
fprintf(stderr, " service: %d\n", ptr->svc);
fprintf(stderr, " cred: %p\n", ptr->cred);
}
#endif /*DEBUG*/
struct rpc_gss_data {
bool_t established; /* context established */
gss_buffer_desc gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier
* to process at end of context negotiation*/
CLIENT *clnt; /* client handle */
gss_name_t name; /* service name */
struct rpc_gss_sec sec; /* security tuple */
gss_ctx_id_t ctx; /* context id */
struct rpc_gss_cred gc; /* client credentials */
u_int win; /* sequence window */
};
#define AUTH_PRIVATE(auth) ((struct rpc_gss_data *)auth->ah_private)
static struct timeval AUTH_TIMEOUT = { 25, 0 };
AUTH *
authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec)
{
AUTH *auth, *save_auth;
struct rpc_gss_data *gd;
OM_uint32 min_stat = 0;
log_debug("in authgss_create()");
memset(&rpc_createerr, 0, sizeof(rpc_createerr));
if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
return (NULL);
}
if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
free(auth);
return (NULL);
}
#ifdef DEBUG
fprintf(stderr, "authgss_create: name is %p\n", name);
#endif
if (name != GSS_C_NO_NAME) {
if (gss_duplicate_name(&min_stat, name, &gd->name)
!= GSS_S_COMPLETE) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
free(auth);
return (NULL);
}
}
else
gd->name = name;
#ifdef DEBUG
fprintf(stderr, "authgss_create: gd->name is %p\n", gd->name);
#endif
gd->clnt = clnt;
gd->ctx = GSS_C_NO_CONTEXT;
gd->sec = *sec;
gd->gc.gc_v = RPCSEC_GSS_VERSION;
gd->gc.gc_proc = RPCSEC_GSS_INIT;
gd->gc.gc_svc = gd->sec.svc;
auth->ah_ops = &authgss_ops;
auth->ah_private = (caddr_t)gd;
save_auth = clnt->cl_auth;
clnt->cl_auth = auth;
if (!authgss_refresh(auth))
auth = NULL;
clnt->cl_auth = save_auth;
return (auth);
}
AUTH *
authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec)
{
AUTH *auth;
OM_uint32 maj_stat = 0, min_stat = 0;
gss_buffer_desc sname;
gss_name_t name = GSS_C_NO_NAME;
log_debug("in authgss_create_default()");
sname.value = service;
sname.length = strlen(service);
maj_stat = gss_import_name(&min_stat, &sname,
(gss_OID)GSS_C_NT_HOSTBASED_SERVICE,
&name);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_import_name", maj_stat, min_stat);
rpc_createerr.cf_stat = RPC_AUTHERROR;
return (NULL);
}
auth = authgss_create(clnt, name, sec);
if (name != GSS_C_NO_NAME) {
#ifdef DEBUG
fprintf(stderr, "authgss_create_default: freeing name %p\n", name);
#endif
gss_release_name(&min_stat, &name);
}
return (auth);
}
bool_t
authgss_get_private_data(AUTH *auth, struct authgss_private_data *pd)
{
struct rpc_gss_data *gd;
log_debug("in authgss_get_private_data()");
if (!auth || !pd)
return (FALSE);
gd = AUTH_PRIVATE(auth);
if (!gd || !gd->established)
return (FALSE);
pd->pd_ctx = gd->ctx;
pd->pd_ctx_hndl = gd->gc.gc_ctx;
pd->pd_seq_win = gd->win;
return (TRUE);
}
static void
authgss_nextverf(AUTH *auth)
{
log_debug("in authgss_nextverf()");
/* no action necessary */
}
static bool_t
authgss_marshal(AUTH *auth, XDR *xdrs)
{
XDR tmpxdrs;
char tmp[MAX_AUTH_BYTES];
struct rpc_gss_data *gd;
gss_buffer_desc rpcbuf, checksum;
OM_uint32 maj_stat, min_stat;
bool_t xdr_stat;
log_debug("in authgss_marshal()");
gd = AUTH_PRIVATE(auth);
if (gd->established)
gd->gc.gc_seq++;
xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE);
if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gc)) {
XDR_DESTROY(&tmpxdrs);
return (FALSE);
}
auth->ah_cred.oa_flavor = RPCSEC_GSS;
auth->ah_cred.oa_base = tmp;
auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
XDR_DESTROY(&tmpxdrs);
if (!xdr_opaque_auth(xdrs, &auth->ah_cred))
return (FALSE);
if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
return (xdr_opaque_auth(xdrs, &_null_auth));
}
/* Checksum serialized RPC header, up to and including credential. */
rpcbuf.length = XDR_GETPOS(xdrs);
XDR_SETPOS(xdrs, 0);
rpcbuf.value = XDR_INLINE(xdrs, rpcbuf.length);
maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
&rpcbuf, &checksum);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_get_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
auth->ah_verf.oa_flavor = RPCSEC_GSS;
auth->ah_verf.oa_base = checksum.value;
auth->ah_verf.oa_length = checksum.length;
xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
gss_release_buffer(&min_stat, &checksum);
return (xdr_stat);
}
static bool_t
authgss_validate(AUTH *auth, struct opaque_auth *verf)
{
struct rpc_gss_data *gd;
u_int num, qop_state;
gss_buffer_desc signbuf, checksum;
OM_uint32 maj_stat, min_stat;
log_debug("in authgss_validate()");
gd = AUTH_PRIVATE(auth);
if (gd->established == FALSE) {
/* would like to do this only on NULL rpc --
* gc->established is good enough.
* save the on the wire verifier to validate last
* INIT phase packet after decode if the major
* status is GSS_S_COMPLETE
*/
if ((gd->gc_wire_verf.value =
mem_alloc(verf->oa_length)) == NULL) {
fprintf(stderr, "gss_validate: out of memory\n");
return (FALSE);
}
memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length);
gd->gc_wire_verf.length = verf->oa_length;
return (TRUE);
}
if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
num = htonl(gd->win);
}
else num = htonl(gd->gc.gc_seq);
signbuf.value = &num;
signbuf.length = sizeof(num);
checksum.value = verf->oa_base;
checksum.length = verf->oa_length;
maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
&checksum, &qop_state);
if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
log_status("gss_verify_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
return (TRUE);
}
static bool_t
authgss_refresh(AUTH *auth)
{
struct rpc_gss_data *gd;
struct rpc_gss_init_res gr;
gss_buffer_desc *recv_tokenp, send_token;
OM_uint32 maj_stat, min_stat, call_stat, ret_flags;
log_debug("in authgss_refresh()");
gd = AUTH_PRIVATE(auth);
if (gd->established)
return (TRUE);
/* GSS context establishment loop. */
memset(&gr, 0, sizeof(gr));
recv_tokenp = GSS_C_NO_BUFFER;
#ifdef DEBUG
print_rpc_gss_sec(&gd->sec);
#endif /*DEBUG*/
for (;;) {
#ifdef DEBUG
/* print the token we just received */
if (recv_tokenp != GSS_C_NO_BUFFER) {
log_debug("The token we just received (length %d):",
recv_tokenp->length);
log_hexdump(recv_tokenp->value, recv_tokenp->length, 0);
}
#endif
maj_stat = gss_init_sec_context(&min_stat,
gd->sec.cred,
&gd->ctx,
gd->name,
gd->sec.mech,
gd->sec.req_flags,
0, /* time req */
NULL, /* channel */
recv_tokenp,
NULL, /* used mech */
&send_token,
&ret_flags,
NULL); /* time rec */
if (recv_tokenp != GSS_C_NO_BUFFER) {
gss_release_buffer(&min_stat, &gr.gr_token);
recv_tokenp = GSS_C_NO_BUFFER;
}
if (maj_stat != GSS_S_COMPLETE &&
maj_stat != GSS_S_CONTINUE_NEEDED) {
log_status("gss_init_sec_context", maj_stat, min_stat);
break;
}
if (send_token.length != 0) {
memset(&gr, 0, sizeof(gr));
#ifdef DEBUG
/* print the token we are about to send */
log_debug("The token being sent (length %d):",
send_token.length);
log_hexdump(send_token.value, send_token.length, 0);
#endif
call_stat = clnt_call(gd->clnt, NULLPROC,
(xdrproc_t)xdr_rpc_gss_init_args,
&send_token,
(xdrproc_t)xdr_rpc_gss_init_res,
(caddr_t)&gr, AUTH_TIMEOUT);
gss_release_buffer(&min_stat, &send_token);
if (call_stat != RPC_SUCCESS ||
(gr.gr_major != GSS_S_COMPLETE &&
gr.gr_major != GSS_S_CONTINUE_NEEDED))
return FALSE;
if (gr.gr_ctx.length != 0) {
if (gd->gc.gc_ctx.value)
gss_release_buffer(&min_stat,
&gd->gc.gc_ctx);
gd->gc.gc_ctx = gr.gr_ctx;
}
if (gr.gr_token.length != 0) {
if (maj_stat != GSS_S_CONTINUE_NEEDED)
break;
recv_tokenp = &gr.gr_token;
}
gd->gc.gc_proc = RPCSEC_GSS_CONTINUE_INIT;
}
/* GSS_S_COMPLETE => check gss header verifier,
* usually checked in gss_validate
*/
if (maj_stat == GSS_S_COMPLETE) {
gss_buffer_desc bufin;
gss_buffer_desc bufout;
u_int seq, qop_state = 0;
seq = htonl(gr.gr_win);
bufin.value = (unsigned char *)&seq;
bufin.length = sizeof(seq);
bufout.value = (unsigned char *)gd->gc_wire_verf.value;
bufout.length = gd->gc_wire_verf.length;
maj_stat = gss_verify_mic(&min_stat, gd->ctx,
&bufin, &bufout, &qop_state);
if (maj_stat != GSS_S_COMPLETE
|| qop_state != gd->sec.qop) {
log_status("gss_verify_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
gd->established = TRUE;
gd->gc.gc_proc = RPCSEC_GSS_DATA;
gd->gc.gc_seq = 0;
gd->win = gr.gr_win;
break;
}
}
/* End context negotiation loop. */
if (gd->gc.gc_proc != RPCSEC_GSS_DATA) {
if (gr.gr_token.length != 0)
gss_release_buffer(&min_stat, &gr.gr_token);
authgss_destroy(auth);
auth = NULL;
rpc_createerr.cf_stat = RPC_AUTHERROR;
return (FALSE);
}
return (TRUE);
}
bool_t
authgss_service(AUTH *auth, int svc)
{
struct rpc_gss_data *gd;
log_debug("in authgss_service()");
if (!auth)
return(FALSE);
gd = AUTH_PRIVATE(auth);
if (!gd || !gd->established)
return (FALSE);
gd->sec.svc = svc;
gd->gc.gc_svc = svc;
return (TRUE);
}
static void
authgss_destroy_context(AUTH *auth)
{
struct rpc_gss_data *gd;
OM_uint32 min_stat;
log_debug("in authgss_destroy_context()");
gd = AUTH_PRIVATE(auth);
if (gd->gc.gc_ctx.length != 0) {
if (gd->established) {
gd->gc.gc_proc = RPCSEC_GSS_DESTROY;
clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT);
}
gss_release_buffer(&min_stat, &gd->gc.gc_ctx);
/* XXX ANDROS check size of context - should be 8 */
memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx));
}
if (gd->ctx != GSS_C_NO_CONTEXT) {
gss_delete_sec_context(&min_stat, &gd->ctx, NULL);
gd->ctx = GSS_C_NO_CONTEXT;
}
/* free saved wire verifier (if any) */
mem_free(gd->gc_wire_verf.value, gd->gc_wire_verf.length);
gd->gc_wire_verf.value = NULL;
gd->gc_wire_verf.length = 0;
gd->established = FALSE;
}
static void
authgss_destroy(AUTH *auth)
{
struct rpc_gss_data *gd;
OM_uint32 min_stat;
log_debug("in authgss_destroy()");
gd = AUTH_PRIVATE(auth);
authgss_destroy_context(auth);
#ifdef DEBUG
fprintf(stderr, "authgss_destroy: freeing name %p\n", gd->name);
#endif
if (gd->name != GSS_C_NO_NAME)
gss_release_name(&min_stat, &gd->name);
free(gd);
free(auth);
}
bool_t
authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
log_debug("in authgss_wrap()");
gd = AUTH_PRIVATE(auth);
if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
return ((*xdr_func)(xdrs, xdr_ptr));
}
return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
gd->ctx, gd->sec.qop,
gd->sec.svc, gd->gc.gc_seq));
}
bool_t
authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
log_debug("in authgss_unwrap()");
gd = AUTH_PRIVATE(auth);
if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
return ((*xdr_func)(xdrs, xdr_ptr));
}
return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
gd->ctx, gd->sec.qop,
gd->sec.svc, gd->gc.gc_seq));
}

177
libtirpc/src/auth_none.c Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
#if defined(LIBC_SCCS) && !defined(lint)
static char *sccsid = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
static char *sccsid = "@(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";
#endif
//#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.12 2002/03/22 23:18:35 obrien Exp $");
*/
/*
* auth_none.c
* Creates a client authentication handle for passing "null"
* credentials and verifiers to remote systems.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <assert.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#define MAX_MARSHAL_SIZE 20
/*
* Authenticator operations routines
*/
static bool_t authnone_marshal (AUTH *, XDR *);
static void authnone_verf (AUTH *);
static bool_t authnone_validate (AUTH *, struct opaque_auth *);
static bool_t authnone_refresh (AUTH *, void *);
static void authnone_destroy (AUTH *);
extern bool_t xdr_opaque_auth();
static struct auth_ops *authnone_ops();
static struct authnone_private {
AUTH no_client;
char marshalled_client[MAX_MARSHAL_SIZE];
u_int mcnt;
} *authnone_private;
AUTH *
authnone_create()
{
struct authnone_private *ap = authnone_private;
XDR xdr_stream;
XDR *xdrs;
extern mutex_t authnone_lock;
mutex_lock(&authnone_lock);
if (ap == 0) {
ap = (struct authnone_private *)calloc(1, sizeof (*ap));
if (ap == 0) {
mutex_unlock(&authnone_lock);
return (0);
}
authnone_private = ap;
}
if (!ap->mcnt) {
ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
ap->no_client.ah_ops = authnone_ops();
xdrs = &xdr_stream;
xdrmem_create(xdrs, ap->marshalled_client,
(u_int)MAX_MARSHAL_SIZE, XDR_ENCODE);
(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
ap->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
}
mutex_unlock(&authnone_lock);
return (&ap->no_client);
}
/*ARGSUSED*/
static bool_t
authnone_marshal(AUTH *client, XDR *xdrs)
{
struct authnone_private *ap;
bool_t dummy;
extern mutex_t authnone_lock;
assert(xdrs != NULL);
ap = authnone_private;
if (ap == NULL) {
mutex_unlock(&authnone_lock);
return (FALSE);
}
dummy = (*xdrs->x_ops->x_putbytes)(xdrs,
ap->marshalled_client, ap->mcnt);
mutex_unlock(&authnone_lock);
return (dummy);
}
/* All these unused parameters are required to keep ANSI-C from grumbling */
/*ARGSUSED*/
static void
authnone_verf(AUTH *client)
{
}
/*ARGSUSED*/
static bool_t
authnone_validate(AUTH *client, struct opaque_auth *opaque)
{
return (TRUE);
}
/*ARGSUSED*/
static bool_t
authnone_refresh(AUTH *client, void *dummy)
{
return (FALSE);
}
/*ARGSUSED*/
static void
authnone_destroy(AUTH *client)
{
}
static struct auth_ops *
authnone_ops()
{
static struct auth_ops ops;
extern mutex_t ops_lock;
/* VARIABLES PROTECTED BY ops_lock: ops */
mutex_lock(&ops_lock);
if (ops.ah_nextverf == NULL) {
ops.ah_nextverf = authnone_verf;
ops.ah_marshal = authnone_marshal;
ops.ah_validate = authnone_validate;
ops.ah_refresh = authnone_refresh;
ops.ah_destroy = authnone_destroy;
}
mutex_unlock(&ops_lock);
return (&ops);
}

634
libtirpc/src/auth_sspi.c Normal file
View file

@ -0,0 +1,634 @@
/*
* auth_sspi.c
*
* RPCSEC_GSS client routines (using the Windows SSPI rather than GSS-API).
*
* Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
* All rights reserved, all wrongs reversed.
*
* COPYRIGHT (c) 2010
* The Regents of the University of Michigan
* ALL RIGHTS RESERVED
*
* Permission is granted to use, copy, create derivative works
* and redistribute this software and such derivative works
* for any purpose, so long as the name of The University of
* Michigan is not used in any advertising or publicity
* pertaining to the use of distribution of this software
* without specific, written prior authorization. If the
* above copyright notice or any other identification of the
* University of Michigan is included in any copy of any
* portion of this software, then the disclaimer below must
* also be included.
*
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
* FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
* PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
* MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
* WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
* REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
* FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
* OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES.
*
*/
#include <wintirpc.h>
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_gss.h>
#include <rpc/clnt.h>
//#include <netinet/in.h>
//#include <gssapi/gssapi.h>
static void authgss_nextverf();
static bool_t authgss_marshal();
static bool_t authgss_refresh();
static bool_t authgss_validate();
static void authgss_destroy();
static void authgss_destroy_context();
static bool_t authgss_wrap();
static bool_t authgss_unwrap();
/*
* from mit-krb5-1.2.1 mechglue/mglueP.h:
* Array of context IDs typed by mechanism OID
*/
typedef struct gss_union_ctx_id_t {
gss_OID mech_type;
gss_ctx_id_t internal_ctx_id;
} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
static struct auth_ops authgss_ops = {
authgss_nextverf,
authgss_marshal,
authgss_validate,
authgss_refresh,
authgss_destroy,
authgss_wrap,
authgss_unwrap
};
#ifdef DEBUG
/* useful as i add more mechanisms */
void
print_rpc_gss_sec(struct rpc_gss_sec *ptr)
{
int i;
char *p;
log_debug("rpc_gss_sec:");
if(ptr->mech == NULL)
log_debug("NULL gss_OID mech");
else {
fprintf(stderr, " mechanism_OID: {");
p = (char *)ptr->mech->elements;
for (i=0; i < ptr->mech->length; i++)
/* First byte of OIDs encoded to save a byte */
if (i == 0) {
int first, second;
if (*p < 40) {
first = 0;
second = *p;
}
else if (40 <= *p && *p < 80) {
first = 1;
second = *p - 40;
}
else if (80 <= *p && *p < 127) {
first = 2;
second = *p - 80;
}
else {
/* Invalid value! */
first = -1;
second = -1;
}
fprintf(stderr, " %u %u", first, second);
p++;
}
else {
fprintf(stderr, " %u", (unsigned char)*p++);
}
fprintf(stderr, " }\n");
}
fprintf(stderr, " qop: %d\n", ptr->qop);
fprintf(stderr, " service: %d\n", ptr->svc);
fprintf(stderr, " cred: %p\n", ptr->cred);
}
#endif /*DEBUG*/
struct rpc_gss_data {
bool_t established; /* context established */
gss_buffer_desc gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier
* to process at end of context negotiation*/
CLIENT *clnt; /* client handle */
gss_name_t name; /* service name */
struct rpc_gss_sec sec; /* security tuple */
gss_ctx_id_t ctx; /* context id */
struct rpc_gss_cred gc; /* client credentials */
u_int win; /* sequence window */
};
#define AUTH_PRIVATE(auth) ((struct rpc_gss_data *)auth->ah_private)
static struct timeval AUTH_TIMEOUT = { 25, 0 };
AUTH *
authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec)
{
AUTH *auth, *save_auth;
struct rpc_gss_data *gd;
OM_uint32 min_stat = 0;
log_debug("in authgss_create()");
memset(&rpc_createerr, 0, sizeof(rpc_createerr));
if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
return (NULL);
}
if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
free(auth);
return (NULL);
}
#ifdef DEBUG
fprintf(stderr, "authgss_create: name is %p\n", name);
#endif
if (name != GSS_C_NO_NAME) {
if (gss_duplicate_name(&min_stat, name, &gd->name)
!= GSS_S_COMPLETE) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = ENOMEM;
free(auth);
return (NULL);
}
}
else
gd->name = name;
#ifdef DEBUG
fprintf(stderr, "authgss_create: gd->name is %p\n", gd->name);
#endif
gd->clnt = clnt;
gd->ctx = GSS_C_NO_CONTEXT;
gd->sec = *sec;
gd->gc.gc_v = RPCSEC_GSS_VERSION;
gd->gc.gc_proc = RPCSEC_GSS_INIT;
gd->gc.gc_svc = gd->sec.svc;
auth->ah_ops = &authgss_ops;
auth->ah_private = (caddr_t)gd;
save_auth = clnt->cl_auth;
clnt->cl_auth = auth;
if (!authgss_refresh(auth))
auth = NULL;
clnt->cl_auth = save_auth;
return (auth);
}
AUTH *
authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec)
{
AUTH *auth;
OM_uint32 maj_stat = 0, min_stat = 0;
gss_buffer_desc sname;
gss_name_t name = GSS_C_NO_NAME;
log_debug("in authgss_create_default()");
sname.value = service;
sname.length = strlen(service);
maj_stat = gss_import_name(&min_stat, &sname,
(gss_OID)GSS_C_NT_HOSTBASED_SERVICE,
&name);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_import_name", maj_stat, min_stat);
rpc_createerr.cf_stat = RPC_AUTHERROR;
return (NULL);
}
auth = authgss_create(clnt, name, sec);
if (name != GSS_C_NO_NAME) {
#ifdef DEBUG
fprintf(stderr, "authgss_create_default: freeing name %p\n", name);
#endif
gss_release_name(&min_stat, &name);
}
return (auth);
}
bool_t
authgss_get_private_data(AUTH *auth, struct authgss_private_data *pd)
{
struct rpc_gss_data *gd;
log_debug("in authgss_get_private_data()");
if (!auth || !pd)
return (FALSE);
gd = AUTH_PRIVATE(auth);
if (!gd || !gd->established)
return (FALSE);
pd->pd_ctx = gd->ctx;
pd->pd_ctx_hndl = gd->gc.gc_ctx;
pd->pd_seq_win = gd->win;
return (TRUE);
}
static void
authgss_nextverf(AUTH *auth)
{
log_debug("in authgss_nextverf()");
/* no action necessary */
}
static bool_t
authgss_marshal(AUTH *auth, XDR *xdrs)
{
XDR tmpxdrs;
char tmp[MAX_AUTH_BYTES];
struct rpc_gss_data *gd;
gss_buffer_desc rpcbuf, checksum;
OM_uint32 maj_stat, min_stat;
bool_t xdr_stat;
log_debug("in authgss_marshal()");
gd = AUTH_PRIVATE(auth);
if (gd->established)
gd->gc.gc_seq++;
xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE);
if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gc)) {
XDR_DESTROY(&tmpxdrs);
return (FALSE);
}
auth->ah_cred.oa_flavor = RPCSEC_GSS;
auth->ah_cred.oa_base = tmp;
auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
XDR_DESTROY(&tmpxdrs);
if (!xdr_opaque_auth(xdrs, &auth->ah_cred))
return (FALSE);
if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
return (xdr_opaque_auth(xdrs, &_null_auth));
}
/* Checksum serialized RPC header, up to and including credential. */
rpcbuf.length = XDR_GETPOS(xdrs);
XDR_SETPOS(xdrs, 0);
rpcbuf.value = XDR_INLINE(xdrs, rpcbuf.length);
maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
&rpcbuf, &checksum);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_get_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
auth->ah_verf.oa_flavor = RPCSEC_GSS;
auth->ah_verf.oa_base = checksum.value;
auth->ah_verf.oa_length = checksum.length;
xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
gss_release_buffer(&min_stat, &checksum);
return (xdr_stat);
}
static bool_t
authgss_validate(AUTH *auth, struct opaque_auth *verf)
{
struct rpc_gss_data *gd;
u_int num, qop_state;
gss_buffer_desc signbuf, checksum;
OM_uint32 maj_stat, min_stat;
log_debug("in authgss_validate()");
gd = AUTH_PRIVATE(auth);
if (gd->established == FALSE) {
/* would like to do this only on NULL rpc --
* gc->established is good enough.
* save the on the wire verifier to validate last
* INIT phase packet after decode if the major
* status is GSS_S_COMPLETE
*/
if ((gd->gc_wire_verf.value =
mem_alloc(verf->oa_length)) == NULL) {
fprintf(stderr, "gss_validate: out of memory\n");
return (FALSE);
}
memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length);
gd->gc_wire_verf.length = verf->oa_length;
return (TRUE);
}
if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
num = htonl(gd->win);
}
else num = htonl(gd->gc.gc_seq);
signbuf.value = &num;
signbuf.length = sizeof(num);
checksum.value = verf->oa_base;
checksum.length = verf->oa_length;
maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
&checksum, &qop_state);
if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
log_status("gss_verify_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
return (TRUE);
}
static bool_t
authgss_refresh(AUTH *auth)
{
struct rpc_gss_data *gd;
struct rpc_gss_init_res gr;
gss_buffer_desc *recv_tokenp, send_token;
OM_uint32 maj_stat, min_stat, call_stat, ret_flags;
log_debug("in authgss_refresh()");
gd = AUTH_PRIVATE(auth);
if (gd->established)
return (TRUE);
/* GSS context establishment loop. */
memset(&gr, 0, sizeof(gr));
recv_tokenp = GSS_C_NO_BUFFER;
#ifdef DEBUG
print_rpc_gss_sec(&gd->sec);
#endif /*DEBUG*/
for (;;) {
#ifdef DEBUG
/* print the token we just received */
if (recv_tokenp != GSS_C_NO_BUFFER) {
log_debug("The token we just received (length %d):",
recv_tokenp->length);
log_hexdump(recv_tokenp->value, recv_tokenp->length, 0);
}
#endif
maj_stat = gss_init_sec_context(&min_stat,
gd->sec.cred,
&gd->ctx,
gd->name,
gd->sec.mech,
gd->sec.req_flags,
0, /* time req */
NULL, /* channel */
recv_tokenp,
NULL, /* used mech */
&send_token,
&ret_flags,
NULL); /* time rec */
if (recv_tokenp != GSS_C_NO_BUFFER) {
gss_release_buffer(&min_stat, &gr.gr_token);
recv_tokenp = GSS_C_NO_BUFFER;
}
if (maj_stat != GSS_S_COMPLETE &&
maj_stat != GSS_S_CONTINUE_NEEDED) {
log_status("gss_init_sec_context", maj_stat, min_stat);
break;
}
if (send_token.length != 0) {
memset(&gr, 0, sizeof(gr));
#ifdef DEBUG
/* print the token we are about to send */
log_debug("The token being sent (length %d):",
send_token.length);
log_hexdump(send_token.value, send_token.length, 0);
#endif
call_stat = clnt_call(gd->clnt, NULLPROC,
(xdrproc_t)xdr_rpc_gss_init_args,
&send_token,
(xdrproc_t)xdr_rpc_gss_init_res,
(caddr_t)&gr, AUTH_TIMEOUT);
gss_release_buffer(&min_stat, &send_token);
if (call_stat != RPC_SUCCESS ||
(gr.gr_major != GSS_S_COMPLETE &&
gr.gr_major != GSS_S_CONTINUE_NEEDED))
return FALSE;
if (gr.gr_ctx.length != 0) {
if (gd->gc.gc_ctx.value)
gss_release_buffer(&min_stat,
&gd->gc.gc_ctx);
gd->gc.gc_ctx = gr.gr_ctx;
}
if (gr.gr_token.length != 0) {
if (maj_stat != GSS_S_CONTINUE_NEEDED)
break;
recv_tokenp = &gr.gr_token;
}
gd->gc.gc_proc = RPCSEC_GSS_CONTINUE_INIT;
}
/* GSS_S_COMPLETE => check gss header verifier,
* usually checked in gss_validate
*/
if (maj_stat == GSS_S_COMPLETE) {
gss_buffer_desc bufin;
gss_buffer_desc bufout;
u_int seq, qop_state = 0;
seq = htonl(gr.gr_win);
bufin.value = (unsigned char *)&seq;
bufin.length = sizeof(seq);
bufout.value = (unsigned char *)gd->gc_wire_verf.value;
bufout.length = gd->gc_wire_verf.length;
maj_stat = gss_verify_mic(&min_stat, gd->ctx,
&bufin, &bufout, &qop_state);
if (maj_stat != GSS_S_COMPLETE
|| qop_state != gd->sec.qop) {
log_status("gss_verify_mic", maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
return (FALSE);
}
gd->established = TRUE;
gd->gc.gc_proc = RPCSEC_GSS_DATA;
gd->gc.gc_seq = 0;
gd->win = gr.gr_win;
break;
}
}
/* End context negotiation loop. */
if (gd->gc.gc_proc != RPCSEC_GSS_DATA) {
if (gr.gr_token.length != 0)
gss_release_buffer(&min_stat, &gr.gr_token);
authgss_destroy(auth);
auth = NULL;
rpc_createerr.cf_stat = RPC_AUTHERROR;
return (FALSE);
}
return (TRUE);
}
bool_t
authgss_service(AUTH *auth, int svc)
{
struct rpc_gss_data *gd;
log_debug("in authgss_service()");
if (!auth)
return(FALSE);
gd = AUTH_PRIVATE(auth);
if (!gd || !gd->established)
return (FALSE);
gd->sec.svc = svc;
gd->gc.gc_svc = svc;
return (TRUE);
}
static void
authgss_destroy_context(AUTH *auth)
{
struct rpc_gss_data *gd;
OM_uint32 min_stat;
log_debug("in authgss_destroy_context()");
gd = AUTH_PRIVATE(auth);
if (gd->gc.gc_ctx.length != 0) {
if (gd->established) {
gd->gc.gc_proc = RPCSEC_GSS_DESTROY;
clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT);
}
gss_release_buffer(&min_stat, &gd->gc.gc_ctx);
/* XXX ANDROS check size of context - should be 8 */
memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx));
}
if (gd->ctx != GSS_C_NO_CONTEXT) {
gss_delete_sec_context(&min_stat, &gd->ctx, NULL);
gd->ctx = GSS_C_NO_CONTEXT;
}
/* free saved wire verifier (if any) */
mem_free(gd->gc_wire_verf.value, gd->gc_wire_verf.length);
gd->gc_wire_verf.value = NULL;
gd->gc_wire_verf.length = 0;
gd->established = FALSE;
}
static void
authgss_destroy(AUTH *auth)
{
struct rpc_gss_data *gd;
OM_uint32 min_stat;
log_debug("in authgss_destroy()");
gd = AUTH_PRIVATE(auth);
authgss_destroy_context(auth);
#ifdef DEBUG
fprintf(stderr, "authgss_destroy: freeing name %p\n", gd->name);
#endif
if (gd->name != GSS_C_NO_NAME)
gss_release_name(&min_stat, &gd->name);
free(gd);
free(auth);
}
bool_t
authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
log_debug("in authgss_wrap()");
gd = AUTH_PRIVATE(auth);
if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
return ((*xdr_func)(xdrs, xdr_ptr));
}
return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
gd->ctx, gd->sec.qop,
gd->sec.svc, gd->gc.gc_seq));
}
bool_t
authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
log_debug("in authgss_unwrap()");
gd = AUTH_PRIVATE(auth);
if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
return ((*xdr_func)(xdrs, xdr_ptr));
}
return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
gd->ctx, gd->sec.qop,
gd->sec.svc, gd->gc.gc_seq));
}

504
libtirpc/src/auth_time.c Normal file
View file

@ -0,0 +1,504 @@
/*
* auth_time.c
*
* This module contains the private function __rpc_get_time_offset()
* which will return the difference in seconds between the local system's
* notion of time and a remote server's notion of time. This must be
* possible without calling any functions that may invoke the name
* service. (netdir_getbyxxx, getXbyY, etc). The function is used in the
* synchronize call of the authdes code to synchronize clocks between
* NIS+ clients and their servers.
*
* Note to minimize the amount of duplicate code, portions of the
* synchronize() function were folded into this code, and the synchronize
* call becomes simply a wrapper around this function. Further, if this
* function is called with a timehost it *DOES* recurse to the name
* server so don't use it in that mode if you are doing name service code.
*
* Copyright (c) 1992 Sun Microsystems Inc.
* All rights reserved.
*
* Side effects :
* When called a client handle to a RPCBIND process is created
* and destroyed. Two strings "netid" and "uaddr" are malloc'd
* and returned. The SIGALRM processing is modified only if
* needed to deal with TCP connections.
*/
//#include <sys/cdefs.h>
#include <wintirpc.h>
//#include <syslog.h>
#include <string.h>
#include <stdlib.h>
//#include <unistd.h>
//#include <netdb.h>
//#include <sys/signal.h>
#include <errno.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/rpc_com.h>
#include <rpc/rpcb_prot.h>
//#include <clnt_soc.h>
//#include <sys/select.h>
#undef NIS
#include <rpcsvc/nis.h>
#ifdef TESTING
#define msg(x) printf("ERROR: %s\n", x)
/* #define msg(x) syslog(LOG_ERR, "%s", x) */
#else
#define msg(x)
#endif
static int saw_alarm = 0;
static void
alarm_hndler(s)
int s;
{
saw_alarm = 1;
return;
}
/*
* The internet time server defines the epoch to be Jan 1, 1900
* whereas UNIX defines it to be Jan 1, 1970. To adjust the result
* from internet time-service time, into UNIX time we subtract the
* following offset :
*/
#define NYEARS (1970 - 1900)
#define TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4)))
/*
* Stolen from rpc.nisd:
* Turn a 'universal address' into a struct sockaddr_in.
* Bletch.
*/
static int uaddr_to_sockaddr(uaddr, sin)
#ifdef foo
endpoint *endpt;
#endif
char *uaddr;
struct sockaddr_in *sin;
{
unsigned char p_bytes[2];
int i;
unsigned long a[6];
i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2],
&a[3], &a[4], &a[5]);
if (i < 6)
return(1);
for (i = 0; i < 4; i++)
sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i);
p_bytes[0] = (unsigned char)a[4] & 0x000000FF;
p_bytes[1] = (unsigned char)a[5] & 0x000000FF;
sin->sin_family = AF_INET; /* always */
bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2);
return (0);
}
/*
* free_eps()
*
* Free the strings that were strduped into the eps structure.
*/
static void
free_eps(eps, num)
endpoint eps[];
int num;
{
int i;
for (i = 0; i < num; i++) {
free(eps[i].uaddr);
free(eps[i].proto);
free(eps[i].family);
}
return;
}
/*
* get_server()
*
* This function constructs a nis_server structure description for the
* indicated hostname.
*
* NOTE: There is a chance we may end up recursing here due to the
* fact that gethostbyname() could do an NIS search. Ideally, the
* NIS+ server will call __rpc_get_time_offset() with the nis_server
* structure already populated.
*/
static nis_server *
get_server(sin, host, srv, eps, maxep)
struct sockaddr_in *sin;
char *host; /* name of the time host */
nis_server *srv; /* nis_server struct to use. */
endpoint eps[]; /* array of endpoints */
int maxep; /* max array size */
{
char hname[256];
int num_ep = 0, i;
struct hostent *he;
struct hostent dummy;
char *ptr[2];
if (host == NULL && sin == NULL)
return (NULL);
if (sin == NULL) {
he = gethostbyname(host);
if (he == NULL)
return(NULL);
} else {
he = &dummy;
ptr[0] = (char *)&sin->sin_addr.s_addr;
ptr[1] = NULL;
dummy.h_addr_list = ptr;
}
/*
* This is lame. We go around once for TCP, then again
* for UDP.
*/
for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
i++, num_ep++) {
struct in_addr *a;
a = (struct in_addr *)he->h_addr_list[i];
snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
eps[num_ep].uaddr = strdup(hname);
eps[num_ep].family = strdup("inet");
eps[num_ep].proto = strdup("tcp");
}
for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
i++, num_ep++) {
struct in_addr *a;
a = (struct in_addr *)he->h_addr_list[i];
snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
eps[num_ep].uaddr = strdup(hname);
eps[num_ep].family = strdup("inet");
eps[num_ep].proto = strdup("udp");
}
srv->name = (nis_name) host;
srv->ep.ep_len = num_ep;
srv->ep.ep_val = eps;
srv->key_type = NIS_PK_NONE;
srv->pkey.n_bytes = NULL;
srv->pkey.n_len = 0;
return (srv);
}
/*
* __rpc_get_time_offset()
*
* This function uses a nis_server structure to contact the a remote
* machine (as named in that structure) and returns the offset in time
* between that machine and this one. This offset is returned in seconds
* and may be positive or negative.
*
* The first time through, a lot of fiddling is done with the netconfig
* stuff to find a suitable transport. The function is very aggressive
* about choosing UDP or at worst TCP if it can. This is because
* those transports support both the RCPBIND call and the internet
* time service.
*
* Once through, *uaddr is set to the universal address of
* the machine and *netid is set to the local netid for the transport
* that uaddr goes with. On the second call, the netconfig stuff
* is skipped and the uaddr/netid pair are used to fetch the netconfig
* structure and to then contact the machine for the time.
*
* td = "server" - "client"
*/
int
__rpc_get_time_offset(td, srv, thost, uaddr, netid)
struct timeval *td; /* Time difference */
nis_server *srv; /* NIS Server description */
char *thost; /* if no server, this is the timehost */
char **uaddr; /* known universal address */
struct sockaddr_in *netid; /* known network identifier */
{
CLIENT *clnt; /* Client handle */
endpoint *ep, /* useful endpoints */
*useep = NULL; /* endpoint of xp */
char *useua = NULL; /* uaddr of selected xp */
int epl, i; /* counters */
enum clnt_stat status; /* result of clnt_call */
long thetime;
long delta;
int needfree = 0;
struct timeval tv;
int time_valid;
int udp_ep = -1, tcp_ep = -1;
int a1, a2, a3, a4;
char ut[64], ipuaddr[64];
endpoint teps[32];
nis_server tsrv;
void (*oldsig)() = NULL; /* old alarm handler */
struct sockaddr_in sin;
SOCKET s = RPC_ANYSOCK;
socklen_t len;
int type = 0;
td->tv_sec = 0;
td->tv_usec = 0;
/*
* First check to see if we need to find and address for this
* server.
*/
if (*uaddr == NULL) {
if ((srv != NULL) && (thost != NULL)) {
msg("both timehost and srv pointer used!");
return (0);
}
if (! srv) {
srv = get_server(netid, thost, &tsrv, teps, 32);
if (srv == NULL) {
msg("unable to contruct server data.");
return (0);
}
needfree = 1; /* need to free data in endpoints */
}
ep = srv->ep.ep_val;
epl = srv->ep.ep_len;
/* Identify the TCP and UDP endpoints */
for (i = 0;
(i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) {
if (strcasecmp(ep[i].proto, "udp") == 0)
udp_ep = i;
if (strcasecmp(ep[i].proto, "tcp") == 0)
tcp_ep = i;
}
/* Check to see if it is UDP or TCP */
if (tcp_ep > -1) {
useep = &ep[tcp_ep];
useua = ep[tcp_ep].uaddr;
type = SOCK_STREAM;
} else if (udp_ep > -1) {
useep = &ep[udp_ep];
useua = ep[udp_ep].uaddr;
type = SOCK_DGRAM;
}
if (useep == NULL) {
msg("no acceptable transport endpoints.");
if (needfree)
free_eps(teps, tsrv.ep.ep_len);
return (0);
}
}
/*
* Create a sockaddr from the uaddr.
*/
if (*uaddr != NULL)
useua = *uaddr;
/* Fixup test for NIS+ */
sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4);
useua = &ipuaddr[0];
bzero((char *)&sin, sizeof(sin));
if (uaddr_to_sockaddr(useua, &sin)) {
msg("unable to translate uaddr to sockaddr.");
if (needfree)
free_eps(teps, tsrv.ep.ep_len);
return (0);
}
/*
* Create the client handle to rpcbind. Note we always try
* version 3 since that is the earliest version that supports
* the RPCB_GETTIME call. Also it is the version that comes
* standard with SVR4. Since most everyone supports TCP/IP
* we could consider trying the rtime call first.
*/
clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0);
if (clnt == NULL) {
msg("unable to create client handle to rpcbind.");
if (needfree)
free_eps(teps, tsrv.ep.ep_len);
return (0);
}
tv.tv_sec = 5;
tv.tv_usec = 0;
time_valid = 0;
status = clnt_call(clnt, RPCBPROC_GETTIME, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_u_long, &thetime, tv);
/*
* The only error we check for is anything but success. In
* fact we could have seen PROGMISMATCH if talking to a 4.1
* machine (pmap v2) or TIMEDOUT if the net was busy.
*/
if (status == RPC_SUCCESS)
time_valid = 1;
else {
int save;
/* Blow away possible stale CLNT handle. */
if (clnt != NULL) {
clnt_destroy(clnt);
clnt = NULL;
}
/*
* Convert PMAP address into timeservice address
* We take advantage of the fact that we "know" what
* the universal address looks like for inet transports.
*
* We also know that the internet timeservice is always
* listening on port 37.
*/
sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4);
if (uaddr_to_sockaddr(ut, &sin)) {
msg("cannot convert timeservice uaddr to sockaddr.");
goto error;
}
s = socket(AF_INET, type, 0);
if (s == INVALID_SOCKET) {
msg("unable to open fd to network.");
goto error;
}
/*
* Now depending on whether or not we're talking to
* UDP we set a timeout or not.
*/
if (type == SOCK_DGRAM) {
struct timeval timeout = { 20, 0 };
struct sockaddr_in from;
fd_set readfds;
int res;
if (sendto(s, (const char *)&thetime, sizeof(thetime), 0,
(struct sockaddr *)&sin, sizeof(sin)) == -1) {
msg("udp : sendto failed.");
goto error;
}
do {
FD_ZERO(&readfds);
FD_SET(s, &readfds);
res = select(_rpc_dtablesize(), &readfds,
(fd_set *)NULL, (fd_set *)NULL, &timeout);
} while (res == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
if (res == SOCKET_ERROR)
goto error;
len = sizeof(from);
res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
(struct sockaddr *)&from, &len);
if (res == SOCKET_ERROR) {
msg("recvfrom failed on udp transport.");
goto error;
}
time_valid = 1;
} else {
int res;
#ifndef _WIN32
oldsig = (void (*)())signal(SIGALRM, alarm_hndler);
saw_alarm = 0; /* global tracking the alarm */
alarm(20); /* only wait 20 seconds */
#else
saw_alarm = 0;
/* XXX Need Windows signal/alarm stuff here XXX */
#endif
res = connect(s, (struct sockaddr *)&sin, sizeof(sin));
if (res == SOCKET_ERROR) {
msg("failed to connect to tcp endpoint.");
goto error;
}
if (saw_alarm) {
msg("alarm caught it, must be unreachable.");
goto error;
}
// res = read(s, (char *)&thetime, sizeof(thetime));
res = recv(s, (char *)&thetime, sizeof(thetime), 0);
if (res != sizeof(thetime)) {
if (saw_alarm)
msg("timed out TCP call.");
else
msg("wrong size of results returned");
goto error;
}
time_valid = 1;
}
save = WSAGetLastError();
(void)closesocket(s);
errno = save;
s = RPC_ANYSOCK;
if (time_valid) {
thetime = ntohl(thetime);
thetime = thetime - TOFFSET; /* adjust to UNIX time */
} else
thetime = 0;
}
gettimeofday(&tv, 0);
error:
/*
* clean up our allocated data structures.
*/
if (s != RPC_ANYSOCK)
(void)closesocket(s);
if (clnt != NULL)
clnt_destroy(clnt);
#ifdef _WIN32
/* XXX Need Windows signal/alarm stuff here XXX */
#else
alarm(0); /* reset that alarm if its outstanding */
if (oldsig) {
signal(SIGALRM, oldsig);
}
#endif
/*
* note, don't free uaddr strings until after we've made a
* copy of them.
*/
if (time_valid) {
if (*uaddr == NULL)
*uaddr = strdup(useua);
/* Round to the nearest second */
tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0;
delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec :
tv.tv_sec - thetime;
td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta;
td->tv_usec = 0;
} else {
msg("unable to get the server's time.");
}
if (needfree)
free_eps(teps, tsrv.ep.ep_len);
return (time_valid);
}

372
libtirpc/src/auth_unix.c Normal file
View file

@ -0,0 +1,372 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* auth_unix.c, Implements UNIX style authentication parameters.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* The system is very weak. The client uses no encryption for it's
* credentials and only sends null verifiers. The server sends backs
* null verifiers or optionally a verifier that suggests a new short hand
* for the credentials.
*
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
//#include <sys/param.h>
#include <assert.h>
//#include <err.h>
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
/* auth_unix.c */
static void authunix_nextverf (AUTH *);
static bool_t authunix_marshal (AUTH *, XDR *);
static bool_t authunix_validate (AUTH *, struct opaque_auth *);
static bool_t authunix_refresh (AUTH *, void *);
static void authunix_destroy (AUTH *);
static void marshal_new_auth (AUTH *);
static struct auth_ops *authunix_ops (void);
/*
* This struct is pointed to by the ah_private field of an auth_handle.
*/
struct audata {
struct opaque_auth au_origcred; /* original credentials */
struct opaque_auth au_shcred; /* short hand cred */
u_long au_shfaults; /* short hand cache faults */
char au_marshed[MAX_AUTH_BYTES];
u_int au_mpos; /* xdr pos at end of marshed */
};
#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
/*
* Create a unix style authenticator.
* Returns an auth handle with the given stuff in it.
*/
AUTH *
authunix_create(machname, uid, gid, len, aup_gids)
char *machname;
uid_t uid;
gid_t gid;
int len;
gid_t *aup_gids;
{
struct authunix_parms aup;
char mymem[MAX_AUTH_BYTES];
struct timeval now;
XDR xdrs;
AUTH *auth;
struct audata *au;
/*
* Allocate and set up auth handle
*/
au = NULL;
auth = mem_alloc(sizeof(*auth));
#ifndef _KERNEL
if (auth == NULL) {
// XXX warnx("authunix_create: out of memory");
goto cleanup_authunix_create;
}
#endif
au = mem_alloc(sizeof(*au));
#ifndef _KERNEL
if (au == NULL) {
// XXX warnx("authunix_create: out of memory");
goto cleanup_authunix_create;
}
#endif
auth->ah_ops = authunix_ops();
auth->ah_private = (caddr_t)au;
auth->ah_verf = au->au_shcred = _null_auth;
au->au_shfaults = 0;
au->au_origcred.oa_base = NULL;
/*
* fill in param struct from the given params
*/
(void)gettimeofday(&now, NULL);
aup.aup_time = now.tv_sec;
aup.aup_machname = machname;
aup.aup_uid = uid;
aup.aup_gid = gid;
aup.aup_len = (u_int)len;
aup.aup_gids = aup_gids;
/*
* Serialize the parameters into origcred
*/
xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
if (! xdr_authunix_parms(&xdrs, &aup))
abort();
au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
au->au_origcred.oa_flavor = AUTH_UNIX;
#ifdef _KERNEL
au->au_origcred.oa_base = mem_alloc((u_int) len);
#else
if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
// XXX warnx("authunix_create: out of memory");
goto cleanup_authunix_create;
}
#endif
memmove(au->au_origcred.oa_base, mymem, (size_t)len);
/*
* set auth handle to reflect new cred.
*/
auth->ah_cred = au->au_origcred;
marshal_new_auth(auth);
return (auth);
#ifndef _KERNEL
cleanup_authunix_create:
if (auth)
mem_free(auth, sizeof(*auth));
if (au) {
if (au->au_origcred.oa_base)
mem_free(au->au_origcred.oa_base, (u_int)len);
mem_free(au, sizeof(*au));
}
return (NULL);
#endif
}
/*
* Returns an auth handle with parameters determined by doing lots of
* syscalls.
*/
AUTH *
authunix_create_default()
{
int len;
char machname[MAXHOSTNAMELEN + 1];
uid_t uid;
gid_t gid;
gid_t gids[NGRPS];
if (gethostname(machname, sizeof machname) == -1)
abort();
machname[sizeof(machname) - 1] = 0;
#if 0
uid = geteuid();
gid = getegid();
if ((len = getgroups(NGRPS, gids)) < 0)
abort();
#else
// XXX Need to figure out what to do here!
uid = 666;
gid = 777;
gids[0] = 0;
len = 0;
#endif
/* XXX: interface problem; those should all have been unsigned */
return (authunix_create(machname, uid, gid, len, gids));
}
/*
* authunix operations
*/
/* ARGSUSED */
static void
authunix_nextverf(auth)
AUTH *auth;
{
/* no action necessary */
}
static bool_t
authunix_marshal(auth, xdrs)
AUTH *auth;
XDR *xdrs;
{
struct audata *au;
assert(auth != NULL);
assert(xdrs != NULL);
au = AUTH_PRIVATE(auth);
return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
}
static bool_t
authunix_validate(auth, verf)
AUTH *auth;
struct opaque_auth *verf;
{
struct audata *au;
XDR xdrs;
assert(auth != NULL);
assert(verf != NULL);
if (verf->oa_flavor == AUTH_SHORT) {
au = AUTH_PRIVATE(auth);
xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
XDR_DECODE);
if (au->au_shcred.oa_base != NULL) {
mem_free(au->au_shcred.oa_base,
au->au_shcred.oa_length);
au->au_shcred.oa_base = NULL;
}
if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
auth->ah_cred = au->au_shcred;
} else {
xdrs.x_op = XDR_FREE;
(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
au->au_shcred.oa_base = NULL;
auth->ah_cred = au->au_origcred;
}
marshal_new_auth(auth);
}
return (TRUE);
}
static bool_t
authunix_refresh(AUTH *auth, void *dummy)
{
struct audata *au = AUTH_PRIVATE(auth);
struct authunix_parms aup;
struct timeval now;
XDR xdrs;
int stat;
assert(auth != NULL);
if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
/* there is no hope. Punt */
return (FALSE);
}
au->au_shfaults ++;
/* first deserialize the creds back into a struct authunix_parms */
aup.aup_machname = NULL;
aup.aup_gids = NULL;
xdrmem_create(&xdrs, au->au_origcred.oa_base,
au->au_origcred.oa_length, XDR_DECODE);
stat = xdr_authunix_parms(&xdrs, &aup);
if (! stat)
goto done;
/* update the time and serialize in place */
(void)gettimeofday(&now, NULL);
aup.aup_time = now.tv_sec;
xdrs.x_op = XDR_ENCODE;
XDR_SETPOS(&xdrs, 0);
stat = xdr_authunix_parms(&xdrs, &aup);
if (! stat)
goto done;
auth->ah_cred = au->au_origcred;
marshal_new_auth(auth);
done:
/* free the struct authunix_parms created by deserializing */
xdrs.x_op = XDR_FREE;
(void)xdr_authunix_parms(&xdrs, &aup);
XDR_DESTROY(&xdrs);
return (stat);
}
static void
authunix_destroy(auth)
AUTH *auth;
{
struct audata *au;
assert(auth != NULL);
au = AUTH_PRIVATE(auth);
mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
if (au->au_shcred.oa_base != NULL)
mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
mem_free(auth->ah_private, sizeof(struct audata));
if (auth->ah_verf.oa_base != NULL)
mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
mem_free(auth, sizeof(*auth));
}
/*
* Marshals (pre-serializes) an auth struct.
* sets private data, au_marshed and au_mpos
*/
static void
marshal_new_auth(auth)
AUTH *auth;
{
XDR xdr_stream;
XDR *xdrs = &xdr_stream;
struct audata *au;
assert(auth != NULL);
au = AUTH_PRIVATE(auth);
xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
(! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
assert(0); // XXX
// XXX warnx("auth_none.c - Fatal marshalling problem");
else
au->au_mpos = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
}
static struct auth_ops *
authunix_ops()
{
static struct auth_ops ops;
extern mutex_t ops_lock;
/* VARIABLES PROTECTED BY ops_lock: ops */
mutex_lock(&ops_lock);
if (ops.ah_nextverf == NULL) {
ops.ah_nextverf = authunix_nextverf;
ops.ah_marshal = authunix_marshal;
ops.ah_validate = authunix_validate;
ops.ah_refresh = authunix_refresh;
ops.ah_destroy = authunix_destroy;
}
mutex_unlock(&ops_lock);
return (&ops);
}

View file

@ -0,0 +1,86 @@
//#include <sys/cdefs.h>
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
/*
* authdes_prot.c, XDR routines for DES authentication
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_des.h>
#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
bool_t
xdr_authdes_cred(xdrs, cred)
XDR *xdrs;
struct authdes_cred *cred;
{
/*
* Unrolled xdr
*/
ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind));
switch (cred->adc_namekind) {
case ADN_FULLNAME:
ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name,
MAXNETNAMELEN));
ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key,
sizeof(des_block)));
ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window,
sizeof(cred->adc_fullname.window)));
return (TRUE);
case ADN_NICKNAME:
ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname,
sizeof(cred->adc_nickname)));
return (TRUE);
default:
return (FALSE);
}
}
bool_t
xdr_authdes_verf(xdrs, verf)
XDR *xdrs;
struct authdes_verf *verf;
{
/*
* Unrolled xdr
*/
ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp,
sizeof(des_block)));
ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u,
sizeof(verf->adv_int_u)));
return (TRUE);
}

356
libtirpc/src/authgss_prot.c Normal file
View file

@ -0,0 +1,356 @@
/*
authgss_prot.c
Copyright (c) 2000 The Regents of the University of Michigan.
All rights reserved.
Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
All rights reserved, all wrongs reversed.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_gss.h>
#include <rpc/rpc.h>
#include <gssapi/gssapi.h>
bool_t
xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
{
bool_t xdr_stat;
xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
xdr_u_int(xdrs, &p->gc_seq) &&
xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
xdr_bytes(xdrs, (char **)&p->gc_ctx.value,
(u_int *)&p->gc_ctx.length, MAX_AUTH_BYTES));
log_debug("xdr_rpc_gss_cred: %s %s "
"(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
(xdr_stat == TRUE) ? "success" : "failure",
p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
p->gc_ctx.value, p->gc_ctx.length);
return (xdr_stat);
}
bool_t
xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
{
bool_t xdr_stat;
xdr_stat = xdr_bytes(xdrs, (char **)&p->value,
(u_int *)&p->length, MAX_NETOBJ_SZ);
log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
(xdr_stat == TRUE) ? "success" : "failure",
p->value, p->length);
return (xdr_stat);
}
bool_t
xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
{
bool_t xdr_stat;
xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value,
(u_int *)&p->gr_ctx.length, MAX_NETOBJ_SZ) &&
xdr_u_int(xdrs, &p->gr_major) &&
xdr_u_int(xdrs, &p->gr_minor) &&
xdr_u_int(xdrs, &p->gr_win) &&
xdr_bytes(xdrs, (char **)&p->gr_token.value,
(u_int *)&p->gr_token.length, MAX_NETOBJ_SZ));
log_debug("xdr_rpc_gss_init_res %s %s "
"(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
(xdr_stat == TRUE) ? "success" : "failure",
p->gr_ctx.value, p->gr_ctx.length,
p->gr_major, p->gr_minor, p->gr_win,
p->gr_token.value, p->gr_token.length);
return (xdr_stat);
}
bool_t
xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
gss_ctx_id_t ctx, gss_qop_t qop,
rpc_gss_svc_t svc, u_int seq)
{
gss_buffer_desc databuf, wrapbuf;
OM_uint32 maj_stat, min_stat;
int start, end, conf_state;
bool_t xdr_stat;
/* Skip databody length. */
start = XDR_GETPOS(xdrs);
XDR_SETPOS(xdrs, start + 4);
/* Marshal rpc_gss_data_t (sequence number + arguments). */
if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
return (FALSE);
end = XDR_GETPOS(xdrs);
/* Set databuf to marshalled rpc_gss_data_t. */
databuf.length = end - start - 4;
XDR_SETPOS(xdrs, start + 4);
databuf.value = XDR_INLINE(xdrs, databuf.length);
xdr_stat = FALSE;
if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
/* Marshal databody_integ length. */
XDR_SETPOS(xdrs, start);
if (!xdr_u_int(xdrs, (u_int *)&databuf.length))
return (FALSE);
/* Checksum rpc_gss_data_t. */
maj_stat = gss_get_mic(&min_stat, ctx, qop,
&databuf, &wrapbuf);
if (maj_stat != GSS_S_COMPLETE) {
log_debug("gss_get_mic failed");
return (FALSE);
}
/* Marshal checksum. */
XDR_SETPOS(xdrs, end);
xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
(u_int *)&wrapbuf.length, MAX_NETOBJ_SZ);
gss_release_buffer(&min_stat, &wrapbuf);
}
else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
/* Encrypt rpc_gss_data_t. */
maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
&conf_state, &wrapbuf);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_wrap", maj_stat, min_stat);
return (FALSE);
}
/* Marshal databody_priv. */
XDR_SETPOS(xdrs, start);
xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
(u_int *)&wrapbuf.length, MAX_NETOBJ_SZ);
gss_release_buffer(&min_stat, &wrapbuf);
}
return (xdr_stat);
}
bool_t
xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
gss_ctx_id_t ctx, gss_qop_t qop,
rpc_gss_svc_t svc, u_int seq)
{
XDR tmpxdrs;
gss_buffer_desc databuf, wrapbuf;
OM_uint32 maj_stat, min_stat;
u_int seq_num, qop_state;
int conf_state;
bool_t xdr_stat;
if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL)
return (TRUE);
memset(&databuf, 0, sizeof(databuf));
memset(&wrapbuf, 0, sizeof(wrapbuf));
if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
/* Decode databody_integ. */
if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length,
MAX_NETOBJ_SZ)) {
log_debug("xdr decode databody_integ failed");
return (FALSE);
}
/* Decode checksum. */
if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
MAX_NETOBJ_SZ)) {
gss_release_buffer(&min_stat, &databuf);
log_debug("xdr decode checksum failed");
return (FALSE);
}
/* Verify checksum and QOP. */
maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
&wrapbuf, &qop_state);
gss_release_buffer(&min_stat, &wrapbuf);
if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
gss_release_buffer(&min_stat, &databuf);
log_status("gss_verify_mic", maj_stat, min_stat);
return (FALSE);
}
}
else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
/* Decode databody_priv. */
if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
MAX_NETOBJ_SZ)) {
log_debug("xdr decode databody_priv failed");
return (FALSE);
}
/* Decrypt databody. */
maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
&conf_state, &qop_state);
gss_release_buffer(&min_stat, &wrapbuf);
/* Verify encryption and QOP. */
if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
conf_state != TRUE) {
gss_release_buffer(&min_stat, &databuf);
log_status("gss_unwrap", maj_stat, min_stat);
return (FALSE);
}
}
/* Decode rpc_gss_data_t (sequence number + arguments). */
xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
(*xdr_func)(&tmpxdrs, xdr_ptr));
XDR_DESTROY(&tmpxdrs);
gss_release_buffer(&min_stat, &databuf);
/* Verify sequence number. */
if (xdr_stat == TRUE && seq_num != seq) {
log_debug("wrong sequence number in databody");
return (FALSE);
}
return (xdr_stat);
}
bool_t
xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
gss_ctx_id_t ctx, gss_qop_t qop,
rpc_gss_svc_t svc, u_int seq)
{
switch (xdrs->x_op) {
case XDR_ENCODE:
return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
ctx, qop, svc, seq));
case XDR_DECODE:
return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
ctx, qop,svc, seq));
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
#ifdef DEBUG
#include <ctype.h>
void
log_debug(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "rpcsec_gss: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void
log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
{
OM_uint32 min;
gss_buffer_desc msg;
int msg_ctx = 0;
fprintf(stderr, "rpcsec_gss: %s: ", m);
gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
&msg_ctx, &msg);
fprintf(stderr, "%s - ", (char *)msg.value);
gss_release_buffer(&min, &msg);
gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
&msg_ctx, &msg);
fprintf(stderr, "%s\n", (char *)msg.value);
gss_release_buffer(&min, &msg);
}
void
log_hexdump(const u_char *buf, int len, int offset)
{
u_int i, j, jm;
int c;
fprintf(stderr, "\n");
for (i = 0; i < len; i += 0x10) {
fprintf(stderr, " %04x: ", (u_int)(i + offset));
jm = len - i;
jm = jm > 16 ? 16 : jm;
for (j = 0; j < jm; j++) {
if ((j % 2) == 1)
fprintf(stderr, "%02x ", (u_int) buf[i+j]);
else
fprintf(stderr, "%02x", (u_int) buf[i+j]);
}
for (; j < 16; j++) {
if ((j % 2) == 1) printf(" ");
else fprintf(stderr, " ");
}
fprintf(stderr, " ");
for (j = 0; j < jm; j++) {
c = buf[i+j];
c = isprint(c) ? c : '.';
fprintf(stderr, "%c", c);
}
fprintf(stderr, "\n");
}
}
#else
void
log_debug(const char *fmt, ...)
{
}
void
log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
{
}
void
log_hexdump(const u_char *buf, int len, int offset)
{
}
#endif

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* authunix_prot.c
* XDR for UNIX style authentication parameters for RPC
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <assert.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
/*
* XDR for unix authentication parameters.
*/
bool_t
xdr_authunix_parms(xdrs, p)
XDR *xdrs;
struct authunix_parms *p;
{
assert(xdrs != NULL);
assert(p != NULL);
if (xdr_u_long(xdrs, &(p->aup_time))
&& xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
&& xdr_u_int(xdrs, &(p->aup_uid))
&& xdr_u_int(xdrs, &(p->aup_gid))
&& xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
&(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
return (TRUE);
}
return (FALSE);
}

274
libtirpc/src/bindresvport.c Normal file
View file

@ -0,0 +1,274 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*
* Portions Copyright(C) 1996, Jason Downs. All rights reserved.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
#include <errno.h>
#include <string.h>
//#include <unistd.h>
#include <rpc/rpc.h>
/*
* Bind a socket to a privileged IP port
*/
int
bindresvport(sd, sin)
SOCKET sd;
struct sockaddr_in *sin;
{
return bindresvport_sa(sd, (struct sockaddr *)sin);
}
#ifdef __linux__
#define STARTPORT 600
#define LOWPORT 512
#define ENDPORT (IPPORT_RESERVED - 1)
#define NPORTS (ENDPORT - STARTPORT + 1)
int
bindresvport_sa(sd, sa)
int sd;
struct sockaddr *sa;
{
int res, af;
struct sockaddr_storage myaddr;
struct sockaddr_in *sin;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
u_int16_t *portp;
static u_int16_t port;
static short startport = STARTPORT;
socklen_t salen;
int nports = ENDPORT - startport + 1;
int endport = ENDPORT;
int i;
if (sa == NULL) {
salen = sizeof(myaddr);
sa = (struct sockaddr *)&myaddr;
if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
return -1; /* errno is correctly set */
af = myaddr.ss_family;
} else
af = sa->sa_family;
switch (af) {
case AF_INET:
sin = (struct sockaddr_in *)sa;
salen = sizeof(struct sockaddr_in);
port = ntohs(sin->sin_port);
portp = &sin->sin_port;
break;
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)sa;
salen = sizeof(struct sockaddr_in6);
port = ntohs(sin6->sin6_port);
portp = &sin6->sin6_port;
break;
#endif
default:
errno = EPFNOSUPPORT;
return (-1);
}
sa->sa_family = af;
if (port == 0) {
port = (getpid() % NPORTS) + STARTPORT;
}
res = -1;
errno = EADDRINUSE;
again:
for (i = 0; i < nports; ++i) {
*portp = htons(port++);
if (port > endport)
port = startport;
res = bind(sd, sa, salen);
if (res >= 0 || errno != EADDRINUSE)
break;
}
if (i == nports && startport != LOWPORT) {
startport = LOWPORT;
endport = STARTPORT - 1;
nports = STARTPORT - LOWPORT;
port = LOWPORT + port % (STARTPORT - LOWPORT);
goto again;
}
return (res);
}
#else
/*----------------------
#if defined(_WIN32)
int
bindresvport_sa(SOCKET sd, struct sockaddr *sa)
{
fprintf(stderr, "Do-nothing bindresvport_sa!\n");
return 0;
}
#else
-------------------------*/
#define IP_PORTRANGE 19
#define IP_PORTRANGE_LOW 2
/*
* Bind a socket to a privileged IP port
*/
int
bindresvport_sa(sd, sa)
SOCKET sd;
struct sockaddr *sa;
{
#ifdef IPV6_PORTRANGE
int old;
#endif
int error, af;
struct sockaddr_storage myaddr;
struct sockaddr_in *sin;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
int proto, portrange, portlow;
u_int16_t *portp;
socklen_t salen;
#ifdef _WIN32
WSAPROTOCOL_INFO proto_info;
int proto_info_size = sizeof(proto_info);
#endif
if (sa == NULL) {
salen = sizeof(myaddr);
sa = (struct sockaddr *)&myaddr;
#ifdef _WIN32
memset(sa, 0, salen);
if (error = getsockopt(sd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&proto_info, &proto_info_size) == SOCKET_ERROR) {
int sockerr = WSAGetLastError();
return -1;
}
af = proto_info.iAddressFamily;
#else
if (getsockname(sd, sa, &salen) == -1)
return -1; /* errno is correctly set */
af = sa->sa_family;
memset(sa, 0, salen);
#endif
} else
af = sa->sa_family;
switch (af) {
case AF_INET:
proto = IPPROTO_IP;
portrange = IP_PORTRANGE;
portlow = IP_PORTRANGE_LOW;
sin = (struct sockaddr_in *)sa;
salen = sizeof(struct sockaddr_in);
portp = &sin->sin_port;
break;
#ifdef INET6
case AF_INET6:
proto = IPPROTO_IPV6;
#ifdef IPV6_PORTRANGE
portrange = IPV6_PORTRANGE;
portlow = IPV6_PORTRANGE_LOW;
#endif
sin6 = (struct sockaddr_in6 *)sa;
salen = sizeof(struct sockaddr_in6);
portp = &sin6->sin6_port;
break;
#endif /* INET6 */
default:
errno = WSAEPFNOSUPPORT;
return (-1);
}
sa->sa_family = (ADDRESS_FAMILY) af;
#ifdef IPV6_PORTRANGE
if (*portp == 0) {
socklen_t oldlen = sizeof(old);
error = getsockopt(sd, proto, portrange, &old, &oldlen);
if (error < 0)
return (error);
error = setsockopt(sd, proto, portrange, &portlow,
sizeof(portlow));
if (error < 0)
return (error);
}
#endif
error = bind(sd, sa, salen);
if (error) {
int err = WSAGetLastError();
}
#ifdef IPV6_PORTRANGE
if (*portp == 0) {
int saved_errno = errno;
if (error < 0) {
if (setsockopt(sd, proto, portrange, &old,
sizeof(old)) < 0)
errno = saved_errno;
return (error);
}
if (sa != (struct sockaddr *)&myaddr) {
/* Hmm, what did the kernel assign? */
if (getsockname(sd, sa, &salen) < 0)
errno = saved_errno;
return (error);
}
}
#endif
return (error);
}
/*
#endif
*/
#endif

707
libtirpc/src/clnt_bcast.c Normal file
View file

@ -0,0 +1,707 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
//#include <sys/cdefs.h>
/*
* clnt_bcast.c
* Client interface to broadcast service.
*
* Copyright (C) 1988, Sun Microsystems, Inc.
*
* The following is kludged-up support for simple rpc broadcasts.
* Someday a large, complicated system will replace these routines.
*/
#include <wintirpc.h>
//#include <sys/socket.h>
#include <sys/types.h>
//#include <sys/queue.h>
/* new queue functions */
//#include <misc/queue.h>
//#include <net/if.h>
//#include <netinet/in.h>
//#include <ifaddrs.h>
//#include <sys/poll.h>
#include <rpc/rpc.h>
#ifdef PORTMAP
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_rmt.h>
#endif /* PORTMAP */
#include <rpc/nettype.h>
//#include <arpa/inet.h>
#ifdef RPC_DEBUG
#include <stdio.h>
#endif
#include <errno.h>
#include <stdlib.h>
//#include <unistd.h>
//#include <netdb.h>
//#include <err.h>
#include <string.h>
#include "rpc_com.h"
#define MAXBCAST 20 /* Max no of broadcasting transports */
#define INITTIME 4000 /* Time to wait initially */
#define WAITTIME 8000 /* Maximum time to wait */
#ifndef POLLRDNORM
# define POLLRDNORM 0x040 /* Normal data may be read. */
#endif
#ifndef POLLRDBAND
# define POLLRDBAND 0x080 /* Priority data may be read. */
#endif
/*
* For now, ASSUME that we do not need this for the Windows port!!!!
*/
#include <wintirpc.h>
#ifdef _WIN32
int __rpc_lowvers = 0;
enum clnt_stat
rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
eachresult, nettype)
rpcprog_t prog; /* program number */
rpcvers_t vers; /* version number */
rpcproc_t proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
resultproc_t eachresult; /* call with each result obtained */
const char *nettype; /* transport type */
{
return 0;
}
#else
/*
* If nettype is NULL, it broadcasts on all the available
* datagram_n transports. May potentially lead to broadacst storms
* and hence should be used with caution, care and courage.
*
* The current parameter xdr packet size is limited by the max tsdu
* size of the transport. If the max tsdu size of any transport is
* smaller than the parameter xdr packet, then broadcast is not
* sent on that transport.
*
* Also, the packet size should be less the packet size of
* the data link layer (for ethernet it is 1400 bytes). There is
* no easy way to find out the max size of the data link layer and
* we are assuming that the args would be smaller than that.
*
* The result size has to be smaller than the transport tsdu size.
*
* If PORTMAP has been defined, we send two packets for UDP, one for
* rpcbind and one for portmap. For those machines which support
* both rpcbind and portmap, it will cause them to reply twice, and
* also here it will get two responses ... inefficient and clumsy.
*/
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_FIRST(head) ((head)->tqh_first)
struct broadif {
int index;
struct sockaddr_storage broadaddr;
TAILQ_ENTRY(broadif) link;
};
typedef TAILQ_HEAD(, broadif) broadlist_t;
int __rpc_getbroadifs(int, int, int, broadlist_t *);
void __rpc_freebroadifs(broadlist_t *);
int __rpc_broadenable(int, int, struct broadif *);
int __rpc_lowvers = 0;
int
__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list)
{
int count = 0;
struct broadif *bip;
struct ifaddrs *ifap, *ifp;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
struct sockaddr_in *sin;
struct addrinfo hints, *res;
#if 0 /* WINDOWS */
if (getifaddrs(&ifp) < 0)
return 0;
#else
/* Use GetAdaptersAddresses() ? */
#endif
memset(&hints, 0, sizeof hints);
hints.ai_family = af;
hints.ai_protocol = proto;
hints.ai_socktype = socktype;
if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0)
return 0;
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
if (ifap->ifa_addr->sa_family != af ||
!(ifap->ifa_flags & IFF_UP))
continue;
bip = (struct broadif *)malloc(sizeof *bip);
if (bip == NULL)
break;
bip->index = if_nametoindex(ifap->ifa_name);
if (
#ifdef INET6
af != AF_INET6 &&
#endif
(ifap->ifa_flags & IFF_BROADCAST) &&
ifap->ifa_broadaddr) {
/* memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
(size_t)ifap->ifa_broadaddr->sa_len);*/
memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
sizeof(bip->broadaddr));
sin = (struct sockaddr_in *)(void *)&bip->broadaddr;
sin->sin_port =
((struct sockaddr_in *)
(void *)res->ai_addr)->sin_port;
} else
#ifdef INET6
if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) {
sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
sin6->sin6_family = af;
sin6->sin6_port =
((struct sockaddr_in6 *)
(void *)res->ai_addr)->sin6_port;
sin6->sin6_scope_id = bip->index;
} else
#endif
{
free(bip);
continue;
}
TAILQ_INSERT_TAIL(list, bip, link);
count++;
}
freeifaddrs(ifp);
freeaddrinfo(res);
return count;
}
void
__rpc_freebroadifs(broadlist_t *list)
{
struct broadif *bip, *next;
bip = TAILQ_FIRST(list);
while (bip != NULL) {
next = TAILQ_NEXT(bip, link);
free(bip);
bip = next;
}
}
int
/*ARGSUSED*/
__rpc_broadenable(int af, int s, struct broadif *bip)
{
int o = 1;
#if 0
if (af == AF_INET6) {
fprintf(stderr, "set v6 multicast if to %d\n", bip->index);
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index,
sizeof bip->index) < 0)
return -1;
} else
#endif
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) == SOCKET_ERROR)
return -1;
return 0;
}
enum clnt_stat
rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
eachresult, inittime, waittime, nettype)
rpcprog_t prog; /* program number */
rpcvers_t vers; /* version number */
rpcproc_t proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
resultproc_t eachresult; /* call with each result obtained */
int inittime; /* how long to wait initially */
int waittime; /* maximum time to wait */
const char *nettype; /* transport type */
{
enum clnt_stat stat = RPC_SUCCESS; /* Return status */
XDR xdr_stream; /* XDR stream */
XDR *xdrs = &xdr_stream;
struct rpc_msg msg; /* RPC message */
struct timeval t;
char *outbuf = NULL; /* Broadcast msg buffer */
char *inbuf = NULL; /* Reply buf */
int inlen;
u_int maxbufsize = 0;
AUTH *sys_auth = authunix_create_default();
int i;
void *handle;
char uaddress[1024]; /* A self imposed limit */
char *uaddrp = uaddress;
int pmap_reply_flag; /* reply recvd from PORTMAP */
/* An array of all the suitable broadcast transports */
struct {
int fd; /* File descriptor */
int af;
int proto;
struct netconfig *nconf; /* Netconfig structure */
u_int asize; /* Size of the addr buf */
u_int dsize; /* Size of the data buf */
struct sockaddr_storage raddr; /* Remote address */
broadlist_t nal;
} fdlist[MAXBCAST];
struct pollfd pfd[MAXBCAST];
size_t fdlistno = 0;
struct r_rpcb_rmtcallargs barg; /* Remote arguments */
struct r_rpcb_rmtcallres bres; /* Remote results */
size_t outlen;
struct netconfig *nconf;
int msec;
int pollretval;
int fds_found;
#ifdef PORTMAP
size_t outlen_pmap = 0;
u_long port; /* Remote port number */
int pmap_flag = 0; /* UDP exists ? */
char *outbuf_pmap = NULL;
struct rmtcallargs barg_pmap; /* Remote arguments */
struct rmtcallres bres_pmap; /* Remote results */
u_int udpbufsz = 0;
#endif /* PORTMAP */
if (sys_auth == NULL) {
return (RPC_SYSTEMERROR);
}
/*
* initialization: create a fd, a broadcast address, and send the
* request on the broadcast transport.
* Listen on all of them and on replies, call the user supplied
* function.
*/
if (nettype == NULL)
nettype = "datagram_n";
if ((handle = __rpc_setconf(nettype)) == NULL) {
return (RPC_UNKNOWNPROTO);
}
while ((nconf = __rpc_getconf(handle)) != NULL) {
int fd;
struct __rpc_sockinfo si;
if (nconf->nc_semantics != NC_TPI_CLTS)
continue;
if (fdlistno >= MAXBCAST)
break; /* No more slots available */
if (!__rpc_nconf2sockinfo(nconf, &si))
continue;
TAILQ_INIT(&fdlist[fdlistno].nal);
if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype,
&fdlist[fdlistno].nal) == 0)
continue;
fd = socket(si.si_af, si.si_socktype, si.si_proto);
if (fd == INVALID_SOCKET) {
stat = RPC_CANTSEND;
continue;
}
fdlist[fdlistno].af = si.si_af;
fdlist[fdlistno].proto = si.si_proto;
fdlist[fdlistno].fd = fd;
fdlist[fdlistno].nconf = nconf;
fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
pfd[fdlistno].events = POLLIN | POLLPRI |
POLLRDNORM | POLLRDBAND;
pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
0);
if (maxbufsize <= fdlist[fdlistno].dsize)
maxbufsize = fdlist[fdlistno].dsize;
#ifdef PORTMAP
if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
udpbufsz = fdlist[fdlistno].dsize;
if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
closesocket(fd);
stat = RPC_SYSTEMERROR;
goto done_broad;
}
pmap_flag = 1;
}
#endif /* PORTMAP */
fdlistno++;
}
if (fdlistno == 0) {
if (stat == RPC_SUCCESS)
stat = RPC_UNKNOWNPROTO;
goto done_broad;
}
if (maxbufsize == 0) {
if (stat == RPC_SUCCESS)
stat = RPC_CANTSEND;
goto done_broad;
}
inbuf = malloc(maxbufsize);
outbuf = malloc(maxbufsize);
if ((inbuf == NULL) || (outbuf == NULL)) {
stat = RPC_SYSTEMERROR;
goto done_broad;
}
/* Serialize all the arguments which have to be sent */
(void) gettimeofday(&t, NULL);
msg.rm_xid = __RPC_GETXID(&t);
msg.rm_direction = CALL;
msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
msg.rm_call.cb_prog = RPCBPROG;
msg.rm_call.cb_vers = RPCBVERS;
msg.rm_call.cb_proc = RPCBPROC_CALLIT;
barg.prog = prog;
barg.vers = vers;
barg.proc = proc;
barg.args.args_val = argsp;
barg.xdr_args = xargs;
bres.addr = uaddrp;
bres.results.results_val = resultsp;
bres.xdr_res = xresults;
msg.rm_call.cb_cred = sys_auth->ah_cred;
msg.rm_call.cb_verf = sys_auth->ah_verf;
xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
if ((!xdr_callmsg(xdrs, &msg)) ||
(!xdr_rpcb_rmtcallargs(xdrs,
(struct rpcb_rmtcallargs *)(void *)&barg))) {
stat = RPC_CANTENCODEARGS;
goto done_broad;
}
outlen = xdr_getpos(xdrs);
xdr_destroy(xdrs);
#ifdef PORTMAP
/* Prepare the packet for version 2 PORTMAP */
if (pmap_flag) {
msg.rm_xid++; /* One way to distinguish */
msg.rm_call.cb_prog = PMAPPROG;
msg.rm_call.cb_vers = PMAPVERS;
msg.rm_call.cb_proc = PMAPPROC_CALLIT;
barg_pmap.prog = prog;
barg_pmap.vers = vers;
barg_pmap.proc = proc;
barg_pmap.args_ptr = argsp;
barg_pmap.xdr_args = xargs;
bres_pmap.port_ptr = &port;
bres_pmap.xdr_results = xresults;
bres_pmap.results_ptr = resultsp;
xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
if ((! xdr_callmsg(xdrs, &msg)) ||
(! xdr_rmtcall_args(xdrs, &barg_pmap))) {
stat = RPC_CANTENCODEARGS;
goto done_broad;
}
outlen_pmap = xdr_getpos(xdrs);
xdr_destroy(xdrs);
}
#endif /* PORTMAP */
/*
* Basic loop: broadcast the packets to transports which
* support data packets of size such that one can encode
* all the arguments.
* Wait a while for response(s).
* The response timeout grows larger per iteration.
*/
for (msec = inittime; msec <= waittime; msec += msec) {
struct broadif *bip;
/* Broadcast all the packets now */
for (i = 0; i < fdlistno; i++) {
if (fdlist[i].dsize < outlen) {
stat = RPC_CANTSEND;
continue;
}
for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
bip = TAILQ_NEXT(bip, link)) {
void *addr;
addr = &bip->broadaddr;
__rpc_broadenable(fdlist[i].af, fdlist[i].fd,
bip);
/*
* Only use version 3 if lowvers is not set
*/
if (!__rpc_lowvers)
if (sendto(fdlist[i].fd, outbuf,
outlen, 0, (struct sockaddr*)addr,
(size_t)fdlist[i].asize) !=
outlen) {
#ifdef RPC_DEBUG
perror("sendto");
#endif
warnx("clnt_bcast: cannot send"
"broadcast packet");
stat = RPC_CANTSEND;
continue;
};
#ifdef RPC_DEBUG
if (!__rpc_lowvers)
fprintf(stderr, "Broadcast packet sent "
"for %s\n",
fdlist[i].nconf->nc_netid);
#endif
#ifdef PORTMAP
/*
* Send the version 2 packet also
* for UDP/IP
*/
if (pmap_flag &&
fdlist[i].proto == IPPROTO_UDP) {
if (sendto(fdlist[i].fd, outbuf_pmap,
outlen_pmap, 0, addr,
(size_t)fdlist[i].asize) !=
outlen_pmap) {
warnx("clnt_bcast: "
"Cannot send broadcast packet");
stat = RPC_CANTSEND;
continue;
}
}
#ifdef RPC_DEBUG
fprintf(stderr, "PMAP Broadcast packet "
"sent for %s\n",
fdlist[i].nconf->nc_netid);
#endif
#endif /* PORTMAP */
}
/* End for sending all packets on this transport */
} /* End for sending on all transports */
if (eachresult == NULL) {
stat = RPC_SUCCESS;
goto done_broad;
}
/*
* Get all the replies from these broadcast requests
*/
recv_again:
switch (pollretval = poll(pfd, fdlistno, msec)) {
case 0: /* timed out */
stat = RPC_TIMEDOUT;
continue;
case -1: /* some kind of error - we ignore it */
goto recv_again;
} /* end of poll results switch */
for (i = fds_found = 0;
i < fdlistno && fds_found < pollretval; i++) {
bool_t done = FALSE;
if (pfd[i].revents == 0)
continue;
else if (pfd[i].revents & POLLNVAL) {
/*
* Something bad has happened to this descri-
* ptor. We can cause _poll() to ignore
* it simply by using a negative fd. We do that
* rather than compacting the pfd[] and fdlist[]
* arrays.
*/
pfd[i].fd = -1;
fds_found++;
continue;
} else
fds_found++;
#ifdef RPC_DEBUG
fprintf(stderr, "response for %s\n",
fdlist[i].nconf->nc_netid);
#endif
try_again:
inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
0, (struct sockaddr *)(void *)&fdlist[i].raddr,
&fdlist[i].asize);
if (inlen < 0) {
if (errno == EINTR)
goto try_again;
warnx("clnt_bcast: Cannot receive reply to "
"broadcast");
stat = RPC_CANTRECV;
continue;
}
if (inlen < sizeof (u_int32_t))
continue; /* Drop that and go ahead */
/*
* see if reply transaction id matches sent id.
* If so, decode the results. If return id is xid + 1
* it was a PORTMAP reply
*/
if (*((u_int32_t *)(void *)(inbuf)) ==
*((u_int32_t *)(void *)(outbuf))) {
pmap_reply_flag = 0;
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where =
(caddr_t)(void *)&bres;
msg.acpted_rply.ar_results.proc =
(xdrproc_t)xdr_rpcb_rmtcallres;
#ifdef PORTMAP
} else if (pmap_flag &&
*((u_int32_t *)(void *)(inbuf)) ==
*((u_int32_t *)(void *)(outbuf_pmap))) {
pmap_reply_flag = 1;
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where =
(caddr_t)(void *)&bres_pmap;
msg.acpted_rply.ar_results.proc =
(xdrproc_t)xdr_rmtcallres;
#endif /* PORTMAP */
} else
continue;
xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
if (xdr_replymsg(xdrs, &msg)) {
if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
(msg.acpted_rply.ar_stat == SUCCESS)) {
struct netbuf *np;
#ifdef PORTMAP
struct netbuf taddr;
struct sockaddr_in sin;
if (pmap_flag && pmap_reply_flag) {
memcpy(&sin, &fdlist[i].raddr, sizeof(sin));
sin.sin_port = htons((u_short)port);
memcpy(&fdlist[i].raddr, &sin, sizeof(sin));
taddr.len = taddr.maxlen =
sizeof(fdlist[i].raddr);
taddr.buf = &fdlist[i].raddr;
done = (*eachresult)(resultsp,
&taddr, fdlist[i].nconf);
} else {
#endif /* PORTMAP */
#ifdef RPC_DEBUG
fprintf(stderr, "uaddr %s\n",
uaddrp);
#endif
np = uaddr2taddr(
fdlist[i].nconf, uaddrp);
done = (*eachresult)(resultsp,
np, fdlist[i].nconf);
free(np);
#ifdef PORTMAP
}
#endif /* PORTMAP */
}
/* otherwise, we just ignore the errors ... */
}
/* else some kind of deserialization problem ... */
xdrs->x_op = XDR_FREE;
msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
(void) xdr_replymsg(xdrs, &msg);
(void) (*xresults)(xdrs, resultsp);
XDR_DESTROY(xdrs);
if (done) {
stat = RPC_SUCCESS;
goto done_broad;
} else {
goto recv_again;
}
} /* The recv for loop */
} /* The giant for loop */
done_broad:
if (inbuf)
(void) free(inbuf);
if (outbuf)
(void) free(outbuf);
#ifdef PORTMAP
if (outbuf_pmap)
(void) free(outbuf_pmap);
#endif /* PORTMAP */
for (i = 0; i < fdlistno; i++) {
(void)closesocket(fdlist[i].fd);
__rpc_freebroadifs(&fdlist[i].nal);
}
AUTH_DESTROY(sys_auth);
(void) __rpc_endconf(handle);
return (stat);
}
enum clnt_stat
rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
eachresult, nettype)
rpcprog_t prog; /* program number */
rpcvers_t vers; /* version number */
rpcproc_t proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
resultproc_t eachresult; /* call with each result obtained */
const char *nettype; /* transport type */
{
enum clnt_stat dummy;
dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp,
xresults, resultsp, eachresult,
INITTIME, WAITTIME, nettype);
return (dummy);
}
#endif

845
libtirpc/src/clnt_dg.c Normal file
View file

@ -0,0 +1,845 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
/*
* Implements a connectionless client side RPC.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <stdint.h>
//#include <sys/poll.h>
//#include <sys/time.h>
//#include <sys/ioctl.h>
#include <rpc/clnt.h>
//#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
//#include <signal.h>
//#include <unistd.h>
//#include <err.h>
#include "rpc_com.h"
#ifdef IP_RECVERR
#include <asm/types.h>
#include <linux/errqueue.h>
#include <sys/uio.h>
#endif
#define MAX_DEFAULT_FDS 20000
static struct clnt_ops *clnt_dg_ops(void);
static bool_t time_not_ok(struct timeval *);
static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
xdrproc_t, void *, struct timeval);
static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
static void clnt_dg_abort(CLIENT *);
static bool_t clnt_dg_control(CLIENT *, u_int, void *);
static void clnt_dg_destroy(CLIENT *);
/*
* This machinery implements per-fd locks for MT-safety. It is not
* sufficient to do per-CLIENT handle locks for MT-safety because a
* user may create more than one CLIENT handle with the same fd behind
* it. Therfore, we allocate an array of flags (dg_fd_locks), protected
* by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
* similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
* CLIENT handle created for that fd.
* The current implementation holds locks across the entire RPC and reply,
* including retransmissions. Yes, this is silly, and as soon as this
* code is proven to work, this should be the first thing fixed. One step
* at a time.
*/
static int *dg_fd_locks;
extern mutex_t clnt_fd_lock;
static cond_t *dg_cv;
#ifndef _WIN32
#define release_fd_lock(fd, mask) { \
mutex_lock(&clnt_fd_lock); \
dg_fd_locks[fd] = 0; \
mutex_unlock(&clnt_fd_lock); \
thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
cond_signal(&dg_cv[fd]); \
}
#else
/* XXX Needs Windows signal/event stuff XXX */
#define release_fd_lock(fd, mask) { \
mutex_lock(&clnt_fd_lock); \
dg_fd_locks[WINSOCK_HANDLE_HASH(fd)] = 0; \
mutex_unlock(&clnt_fd_lock); \
\
cond_signal(&dg_cv[WINSOCK_HANDLE_HASH(fd)]); \
}
#endif
static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
/*
* Private data kept per client handle
*/
struct cu_data {
SOCKET cu_fd; /* connections fd */
bool_t cu_closeit; /* opened by library */
struct sockaddr_storage cu_raddr; /* remote address */
int cu_rlen;
struct timeval cu_wait; /* retransmit interval */
struct timeval cu_total; /* total time for the call */
struct rpc_err cu_error;
XDR cu_outxdrs;
u_int cu_xdrpos;
u_int cu_sendsz; /* send size */
char *cu_outbuf;
u_int cu_recvsz; /* recv size */
int cu_async;
int cu_connect; /* Use connect(). */
int cu_connected; /* Have done connect(). */
char cu_inbuf[1];
};
/*
* Connection less client creation returns with client handle parameters.
* Default options are set, which the user can change using clnt_control().
* fd should be open and bound.
* NB: The rpch->cl_auth is initialized to null authentication.
* Caller may wish to set this something more useful.
*
* sendsz and recvsz are the maximum allowable packet sizes that can be
* sent and received. Normally they are the same, but they can be
* changed to improve the program efficiency and buffer allocation.
* If they are 0, use the transport default.
*
* If svcaddr is NULL, returns NULL.
*/
CLIENT *
clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
SOCKET fd; /* open file descriptor */
const struct netbuf *svcaddr; /* servers address */
rpcprog_t program; /* program number */
rpcvers_t version; /* version number */
u_int sendsz; /* buffer recv size */
u_int recvsz; /* buffer send size */
{
CLIENT *cl = NULL; /* client handle */
struct cu_data *cu = NULL; /* private data */
struct timeval now;
struct rpc_msg call_msg;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
struct __rpc_sockinfo si;
u_long one = 1;
#ifndef _WIN32
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&clnt_fd_lock);
if (dg_fd_locks == (int *) NULL) {
int cv_allocsz;
size_t fd_allocsz;
int dtbsize = __rpc_dtbsize();
fd_allocsz = dtbsize * sizeof (int);
dg_fd_locks = (int *) mem_alloc(fd_allocsz);
if (dg_fd_locks == (int *) NULL) {
mutex_unlock(&clnt_fd_lock);
// thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err1;
} else
memset(dg_fd_locks, 0, fd_allocsz);
cv_allocsz = dtbsize * sizeof (cond_t);
dg_cv = (cond_t *) mem_alloc(cv_allocsz);
if (dg_cv == (cond_t *) NULL) {
mem_free(dg_fd_locks, fd_allocsz);
dg_fd_locks = (int *) NULL;
mutex_unlock(&clnt_fd_lock);
// thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err1;
} else {
int i;
for (i = 0; i < dtbsize; i++)
cond_init(&dg_cv[i], 0, (void *) 0);
}
}
mutex_unlock(&clnt_fd_lock);
// thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
if (svcaddr == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
return (NULL);
}
if (!__rpc_fd2sockinfo(fd, &si)) {
rpc_createerr.cf_stat = RPC_TLIERROR;
rpc_createerr.cf_error.re_errno = 0;
return (NULL);
}
/*
* Find the receive and the send size
*/
sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
if ((sendsz == 0) || (recvsz == 0)) {
rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
rpc_createerr.cf_error.re_errno = 0;
return (NULL);
}
if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
goto err1;
/*
* Should be multiple of 4 for XDR.
*/
sendsz = ((sendsz + 3) / 4) * 4;
recvsz = ((recvsz + 3) / 4) * 4;
cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
if (cu == NULL)
goto err1;
(void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
cu->cu_rlen = svcaddr->len;
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
/* Other values can also be set through clnt_control() */
cu->cu_wait.tv_sec = 15; /* heuristically chosen */
cu->cu_wait.tv_usec = 0;
cu->cu_total.tv_sec = -1;
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
cu->cu_async = FALSE;
cu->cu_connect = FALSE;
cu->cu_connected = FALSE;
(void) gettimeofday(&now, NULL);
// call_msg.rm_xid = __RPC_GETXID(&now);
call_msg.rm_xid = ((u_int32_t)_getpid() ^ (u_int32_t)(&now)->tv_sec ^ (u_int32_t)(&now)->tv_usec);
call_msg.rm_call.cb_prog = program;
call_msg.rm_call.cb_vers = version;
xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */
rpc_createerr.cf_error.re_errno = 0;
goto err2;
}
cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
/* XXX fvdl - do we still want this? */
#if 0
(void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
#endif
#ifdef IP_RECVERR
{
int on = 1;
setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on));
}
#endif
ioctlsocket(fd, FIONBIO, &one);
/*
* By default, closeit is always FALSE. It is users responsibility
* to do a close on it, else the user may use clnt_control
* to let clnt_destroy do it for him/her.
*/
cu->cu_closeit = FALSE;
cu->cu_fd = fd;
cl->cl_ops = clnt_dg_ops();
cl->cl_private = (caddr_t)(void *)cu;
cl->cl_auth = authnone_create();
cl->cl_tp = NULL;
cl->cl_netid = NULL;
return (cl);
err1:
//warnx(mem_err_clnt_dg);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
err2:
if (cl) {
mem_free(cl, sizeof (CLIENT));
if (cu)
mem_free(cu, sizeof (*cu) + sendsz + recvsz);
}
return (NULL);
}
static enum clnt_stat
clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
CLIENT *cl; /* client handle */
rpcproc_t proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
void *argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
void *resultsp; /* pointer to results */
struct timeval utimeout; /* seconds to wait before giving up */
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
XDR *xdrs;
size_t outlen = 0;
struct rpc_msg reply_msg;
XDR reply_xdrs;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
struct pollfd fd;
int total_time, nextsend_time, tv=0;
struct sockaddr *sa;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
socklen_t inlen, salen;
ssize_t recvlen = 0;
int rpc_lock_value;
u_int32_t xid, inval, outval;
outlen = 0;
#ifndef _WIN32
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)])
cond_wait(&dg_cv[WINSOCK_HANDLE_HASH(cu->cu_fd)], &clnt_fd_lock);
rpc_lock_value = 1;
dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)] = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
} else {
timeout = cu->cu_total; /* use default timeout */
}
total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
if (cu->cu_connect && !cu->cu_connected) {
if (connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
cu->cu_rlen) < 0) {
cu->cu_error.re_errno = errno;
cu->cu_error.re_status = RPC_CANTSEND;
goto out;
}
cu->cu_connected = 1;
}
if (cu->cu_connected) {
sa = NULL;
salen = 0;
} else {
sa = (struct sockaddr *)&cu->cu_raddr;
salen = cu->cu_rlen;
}
/* Clean up in case the last call ended in a longjmp(3) call. */
call_again:
xdrs = &(cu->cu_outxdrs);
if (cu->cu_async == TRUE && xargs == NULL)
goto get_reply;
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, cu->cu_xdrpos);
/*
* the transaction is the first thing in the out buffer
* XXX Yes, and it's in network byte order, so we should to
* be careful when we increment it, shouldn't we.
*/
xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf));
xid++;
*(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid);
if ((! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp))) {
cu->cu_error.re_status = RPC_CANTENCODEARGS;
goto out;
}
outlen = (size_t)XDR_GETPOS(xdrs);
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
cu->cu_error.re_status = RPC_TIMEDOUT;
goto out;
}
send_again:
if (total_time <= 0) {
cu->cu_error.re_status = RPC_TIMEDOUT;
goto out;
}
nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
if (sendto(cu->cu_fd, cu->cu_outbuf, (int)outlen, 0, sa, salen) != outlen) {
cu->cu_error.re_errno = errno;
cu->cu_error.re_status = RPC_CANTSEND;
goto out;
}
get_reply:
/*
* sub-optimal code appears here because we have
* some clock time to spare while the packets are in flight.
* (We assume that this is actually only executed once.)
*/
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
fd.fd = cu->cu_fd;
fd.events = POLLIN;
fd.revents = 0;
while (total_time > 0) {
tv = total_time < nextsend_time ? total_time : nextsend_time;
switch (poll(&fd, 1, tv)) {
case 0:
total_time -= tv;
goto send_again;
// XXX CHECK THIS FOR WINDOWS!
case -1:
if (errno == EINTR)
continue;
cu->cu_error.re_status = RPC_CANTRECV;
cu->cu_error.re_errno = errno;
goto out;
}
break;
}
#ifdef IP_RECVERR
if (fd.revents & POLLERR)
{
struct msghdr msg;
struct cmsghdr *cmsg;
struct sock_extended_err *e;
struct sockaddr_in err_addr;
struct sockaddr_in *sin = (struct sockaddr_in *)&cu->cu_raddr;
struct iovec iov;
char *cbuf = (char *) alloca (outlen + 256);
int ret;
iov.iov_base = cbuf + 256;
iov.iov_len = outlen;
msg.msg_name = (void *) &err_addr;
msg.msg_namelen = sizeof (err_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cbuf;
msg.msg_controllen = 256;
ret = recvmsg (cu->cu_fd, &msg, MSG_ERRQUEUE);
if (ret >= 0
&& memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0
&& (msg.msg_flags & MSG_ERRQUEUE)
&& ((msg.msg_namelen == 0
&& ret >= 12)
|| (msg.msg_namelen == sizeof (err_addr)
&& err_addr.sin_family == AF_INET
&& memcmp (&err_addr.sin_addr, &sin->sin_addr,
sizeof (err_addr.sin_addr)) == 0
&& err_addr.sin_port == sin->sin_port)))
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
cmsg = CMSG_NXTHDR (&msg, cmsg))
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
release_fd_lock(cu->cu_fd, mask);
return (cu->cu_error.re_status = RPC_CANTRECV);
}
}
#endif
/* We have some data now */
do {
recvlen = recvfrom(cu->cu_fd, cu->cu_inbuf,
cu->cu_recvsz, 0, NULL, NULL);
errno = WSAGetLastError();
} while (recvlen == SOCKET_ERROR && errno == WSAEINTR);
if (recvlen == SOCKET_ERROR && errno != WSAEWOULDBLOCK) {
cu->cu_error.re_errno = errno;
cu->cu_error.re_status = RPC_CANTRECV;
goto out;
}
if (recvlen < sizeof(u_int32_t)) {
total_time -= tv;
goto send_again;
}
if (cu->cu_async == TRUE)
inlen = (socklen_t)recvlen;
else {
memcpy(&inval, cu->cu_inbuf, sizeof(u_int32_t));
memcpy(&outval, cu->cu_outbuf, sizeof(u_int32_t));
if (inval != outval) {
total_time -= tv;
goto send_again;
}
inlen = (socklen_t)recvlen;
}
/*
* now decode and validate the response
*/
xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE);
ok = xdr_replymsg(&reply_xdrs, &reply_msg);
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
if (ok) {
if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
(reply_msg.acpted_rply.ar_stat == SUCCESS))
cu->cu_error.re_status = RPC_SUCCESS;
else
_seterr_reply(&reply_msg, &(cu->cu_error));
if (cu->cu_error.re_status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(cl->cl_auth,
&reply_msg.acpted_rply.ar_verf)) {
cu->cu_error.re_status = RPC_AUTHERROR;
cu->cu_error.re_why = AUTH_INVALIDRESP;
}
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth(xdrs,
&(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
/*
* If unsuccesful AND error is an authentication error
* then refresh credentials and try again, else break
*/
else if (cu->cu_error.re_status == RPC_AUTHERROR)
/* maybe our credentials need to be refreshed ... */
if (nrefreshes > 0 &&
AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
nrefreshes--;
goto call_again;
}
/* end of unsuccessful completion */
} /* end of valid reply message */
else {
cu->cu_error.re_status = RPC_CANTDECODERES;
}
out:
release_fd_lock(cu->cu_fd, mask);
return (cu->cu_error.re_status);
}
static void
clnt_dg_geterr(cl, errp)
CLIENT *cl;
struct rpc_err *errp;
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
*errp = cu->cu_error;
}
static bool_t
clnt_dg_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
void *res_ptr;
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
XDR *xdrs = &(cu->cu_outxdrs);
bool_t dummy;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)])
cond_wait(&dg_cv[WINSOCK_HANDLE_HASH(cu->cu_fd)], &clnt_fd_lock);
xdrs->x_op = XDR_FREE;
dummy = (*xdr_res)(xdrs, res_ptr);
mutex_unlock(&clnt_fd_lock);
// thr_sigsetmask(SIG_SETMASK, &mask, NULL);
cond_signal(&dg_cv[WINSOCK_HANDLE_HASH(cu->cu_fd)]);
return (dummy);
}
/*ARGSUSED*/
static void
clnt_dg_abort(h)
CLIENT *h;
{
}
static bool_t
clnt_dg_control(cl, request, info)
CLIENT *cl;
u_int request;
void *info;
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
struct netbuf *addr;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
int rpc_lock_value;
#ifndef _WIN32
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)])
cond_wait(&dg_cv[WINSOCK_HANDLE_HASH(cu->cu_fd)], &clnt_fd_lock);
rpc_lock_value = 1;
dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)] = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
switch (request) {
case CLSET_FD_CLOSE:
cu->cu_closeit = TRUE;
release_fd_lock(cu->cu_fd, mask);
return (TRUE);
case CLSET_FD_NCLOSE:
cu->cu_closeit = FALSE;
release_fd_lock(cu->cu_fd, mask);
return (TRUE);
}
/* for other requests which use info */
if (info == NULL) {
release_fd_lock(cu->cu_fd, mask);
return (FALSE);
}
switch (request) {
case CLSET_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
release_fd_lock(cu->cu_fd, mask);
return (FALSE);
}
cu->cu_total = *(struct timeval *)info;
break;
case CLGET_TIMEOUT:
*(struct timeval *)info = cu->cu_total;
break;
case CLGET_SERVER_ADDR: /* Give him the fd address */
/* Now obsolete. Only for backward compatibility */
(void) memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen);
break;
case CLSET_RETRY_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
release_fd_lock(cu->cu_fd, mask);
return (FALSE);
}
cu->cu_wait = *(struct timeval *)info;
break;
case CLGET_RETRY_TIMEOUT:
*(struct timeval *)info = cu->cu_wait;
break;
case CLGET_FD:
*(SOCKET *)info = cu->cu_fd;
break;
case CLGET_SVC_ADDR:
addr = (struct netbuf *)info;
addr->buf = &cu->cu_raddr;
addr->len = cu->cu_rlen;
addr->maxlen = sizeof cu->cu_raddr;
break;
case CLSET_SVC_ADDR: /* set to new address */
addr = (struct netbuf *)info;
if (addr->len < sizeof cu->cu_raddr) {
release_fd_lock(cu->cu_fd, mask);
return (FALSE);
}
(void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
cu->cu_rlen = addr->len;
break;
case CLGET_XID:
/*
* use the knowledge that xid is the
* first element in the call structure *.
* This will get the xid of the PREVIOUS call
*/
*(u_int32_t *)info =
ntohl(*(u_int32_t *)(void *)cu->cu_outbuf);
break;
case CLSET_XID:
/* This will set the xid of the NEXT call */
*(u_int32_t *)(void *)cu->cu_outbuf =
htonl(*(u_int32_t *)info - 1);
/* decrement by 1 as clnt_dg_call() increments once */
break;
case CLGET_VERS:
/*
* This RELIES on the information that, in the call body,
* the version number field is the fifth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_int32_t *)info =
ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
4 * BYTES_PER_XDR_UNIT));
break;
case CLSET_VERS:
*(u_int32_t *)(void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
= htonl(*(u_int32_t *)info);
break;
case CLGET_PROG:
/*
* This RELIES on the information that, in the call body,
* the program number field is the fourth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_int32_t *)info =
ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
3 * BYTES_PER_XDR_UNIT));
break;
case CLSET_PROG:
*(u_int32_t *)(void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
= htonl(*(u_int32_t *)info);
break;
case CLSET_ASYNC:
cu->cu_async = *(int *)info;
break;
case CLSET_CONNECT:
cu->cu_connect = *(int *)info;
break;
default:
release_fd_lock(cu->cu_fd, mask);
return (FALSE);
}
release_fd_lock(cu->cu_fd, mask);
return (TRUE);
}
static void
clnt_dg_destroy(cl)
CLIENT *cl;
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
SOCKET cu_fd = cu->cu_fd;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[WINSOCK_HANDLE_HASH(cu_fd)])
cond_wait(&dg_cv[WINSOCK_HANDLE_HASH(cu_fd)], &clnt_fd_lock);
if (cu->cu_closeit)
(void)closesocket(cu_fd);
XDR_DESTROY(&(cu->cu_outxdrs));
mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
if (cl->cl_netid && cl->cl_netid[0])
mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
if (cl->cl_tp && cl->cl_tp[0])
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof (CLIENT));
mutex_unlock(&clnt_fd_lock);
// thr_sigsetmask(SIG_SETMASK, &mask, NULL);
cond_signal(&dg_cv[WINSOCK_HANDLE_HASH(cu_fd)]);
}
static struct clnt_ops *
clnt_dg_ops()
{
static struct clnt_ops ops;
extern mutex_t ops_lock;
#ifndef _WIN32
sigset_t mask;
sigset_t newmask;
/* VARIABLES PROTECTED BY ops_lock: ops */
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
#else
/* XXX Need Windows signal/event stuff here XXX */
#endif
mutex_lock(&ops_lock);
if (ops.cl_call == NULL) {
ops.cl_call = clnt_dg_call;
ops.cl_abort = clnt_dg_abort;
ops.cl_geterr = clnt_dg_geterr;
ops.cl_freeres = clnt_dg_freeres;
ops.cl_destroy = clnt_dg_destroy;
ops.cl_control = clnt_dg_control;
}
mutex_unlock(&ops_lock);
// thr_sigsetmask(SIG_SETMASK, &mask, NULL);
return (&ops);
}
/*
* Make sure that the time is not garbage. -1 value is allowed.
*/
static bool_t
time_not_ok(t)
struct timeval *t;
{
return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
t->tv_usec < -1 || t->tv_usec > 1000000);
}

453
libtirpc/src/clnt_generic.c Normal file
View file

@ -0,0 +1,453 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1996,1998 by Sun Microsystems, Inc.
* All rights reserved.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <sys/types.h>
//#include <sys/fcntl.h>
#include <fcntl.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
//#include <netinet/tcp.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
//#include <netdb.h>
//#include <syslog.h>
#include <rpc/rpc.h>
#include <rpc/nettype.h>
//#include <unistd.h>
#include "rpc_com.h"
extern bool_t __rpc_is_local_host(const char *);
#if 0 /* WINDOWS */
int __rpc_raise_fd(int);
#endif
#ifndef NETIDLEN
#define NETIDLEN 32
#endif
/*
* Generic client creation with version checking the value of
* vers_out is set to the highest server supported value
* vers_low <= vers_out <= vers_high AND an error results
* if this can not be done.
*
* It calls clnt_create_vers_timed() with a NULL value for the timeout
* pointer, which indicates that the default timeout should be used.
*/
CLIENT *
clnt_create_vers(const char *hostname, const rpcprog_t prog, rpcvers_t *vers_out,
const rpcvers_t vers_low, const rpcvers_t vers_high, const char *nettype)
{
return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low,
vers_high, nettype, NULL));
}
/*
* This the routine has the same definition as clnt_create_vers(),
* except it takes an additional timeout parameter - a pointer to
* a timeval structure. A NULL value for the pointer indicates
* that the default timeout value should be used.
*/
CLIENT *
clnt_create_vers_timed(const char *hostname, const rpcprog_t prog,
rpcvers_t *vers_out, const rpcvers_t vers_low_in, const rpcvers_t vers_high_in,
const char *nettype, const struct timeval *tp)
{
CLIENT *clnt;
struct timeval to;
enum clnt_stat rpc_stat;
struct rpc_err rpcerr;
rpcvers_t vers_high = vers_high_in;
rpcvers_t vers_low = vers_low_in;
clnt = clnt_create_timed(hostname, prog, vers_high, nettype, tp);
if (clnt == NULL) {
return (NULL);
}
to.tv_sec = 10;
to.tv_usec = 0;
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
(char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = vers_high;
return (clnt);
}
while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) {
unsigned int minvers, maxvers;
clnt_geterr(clnt, &rpcerr);
minvers = rpcerr.re_vers.low;
maxvers = rpcerr.re_vers.high;
if (maxvers < vers_high)
vers_high = maxvers;
else
vers_high--;
if (minvers > vers_low)
vers_low = minvers;
if (vers_low > vers_high) {
goto error;
}
CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high);
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
(char *)NULL, (xdrproc_t)xdr_void,
(char *)NULL, to);
if (rpc_stat == RPC_SUCCESS) {
*vers_out = vers_high;
return (clnt);
}
}
clnt_geterr(clnt, &rpcerr);
error:
rpc_createerr.cf_stat = rpc_stat;
rpc_createerr.cf_error = rpcerr;
clnt_destroy(clnt);
return (NULL);
}
/*
* Top level client creation routine.
* Generic client creation: takes (servers name, program-number, nettype) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of _ioctl()'s.
*
* It tries for all the netids in that particular class of netid until
* it succeeds.
* XXX The error message in the case of failure will be the one
* pertaining to the last create error.
*
* It calls clnt_create_timed() with the default timeout.
*/
CLIENT *
clnt_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
const char *nettype)
{
return (clnt_create_timed(hostname, prog, vers, nettype, NULL));
}
/*
* This the routine has the same definition as clnt_create(),
* except it takes an additional timeout parameter - a pointer to
* a timeval structure. A NULL value for the pointer indicates
* that the default timeout value should be used.
*
* This function calls clnt_tp_create_timed().
*/
CLIENT *
clnt_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
const char *netclass, const struct timeval *tp)
{
struct netconfig *nconf;
CLIENT *clnt = NULL;
void *handle;
enum clnt_stat save_cf_stat = RPC_SUCCESS;
struct rpc_err save_cf_error;
char nettype_array[NETIDLEN];
char *nettype = &nettype_array[0];
if (netclass == NULL)
nettype = NULL;
else {
size_t len = strlen(netclass);
if (len >= sizeof (nettype_array)) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
strcpy(nettype, netclass);
}
if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
rpc_createerr.cf_stat = RPC_SUCCESS;
while (clnt == NULL) {
if ((nconf = __rpc_getconf(handle)) == NULL) {
if (rpc_createerr.cf_stat == RPC_SUCCESS)
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
break;
}
#ifdef CLNT_DEBUG
printf("trying netid %s\n", nconf->nc_netid);
#endif
clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp);
if (clnt)
break;
else {
/*
* Since we didn't get a name-to-address
* translation failure here, we remember
* this particular error. The object of
* this is to enable us to return to the
* caller a more-specific error than the
* unhelpful ``Name to address translation
* failed'' which might well occur if we
* merely returned the last error (because
* the local loopbacks are typically the
* last ones in /etc/netconfig and the most
* likely to be unable to translate a host
* name). We also check for a more
* meaningful error than ``unknown host
* name'' for the same reasons.
*/
if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE &&
rpc_createerr.cf_stat != RPC_UNKNOWNHOST) {
save_cf_stat = rpc_createerr.cf_stat;
save_cf_error = rpc_createerr.cf_error;
}
}
}
/*
* Attempt to return an error more specific than ``Name to address
* translation failed'' or ``unknown host name''
*/
if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE ||
rpc_createerr.cf_stat == RPC_UNKNOWNHOST) &&
(save_cf_stat != RPC_SUCCESS)) {
rpc_createerr.cf_stat = save_cf_stat;
rpc_createerr.cf_error = save_cf_error;
}
__rpc_endconf(handle);
return (clnt);
}
/*
* Generic client creation: takes (servers name, program-number, netconf) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of _ioctl()'s : clnt_control()
* It finds out the server address from rpcbind and calls clnt_tli_create().
*
* It calls clnt_tp_create_timed() with the default timeout.
*/
CLIENT *
clnt_tp_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
const struct netconfig *nconf)
{
return (clnt_tp_create_timed(hostname, prog, vers, nconf, NULL));
}
/*
* This has the same definition as clnt_tp_create(), except it
* takes an additional parameter - a pointer to a timeval structure.
* A NULL value for the timeout pointer indicates that the default
* value for the timeout should be used.
*/
CLIENT *
clnt_tp_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
const struct netconfig *nconf, const struct timeval *tp)
{
struct netbuf *svcaddr; /* servers address */
CLIENT *cl = NULL; /* client handle */
if (nconf == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
/*
* Get the address of the server
*/
if ((svcaddr = __rpcb_findaddr_timed(prog, vers,
(struct netconfig *)nconf, (char *)hostname,
&cl, (struct timeval *)tp)) == NULL) {
/* appropriate error number is set by rpcbind libraries */
return (NULL);
}
if (cl == NULL) {
cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
prog, vers, 0, 0, NULL, NULL, NULL);
} else {
/* Reuse the CLIENT handle and change the appropriate fields */
if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
if (cl->cl_netid == NULL)
cl->cl_netid = strdup(nconf->nc_netid);
if (cl->cl_tp == NULL)
cl->cl_tp = strdup(nconf->nc_device);
(void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
(void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
} else {
CLNT_DESTROY(cl);
cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
prog, vers, 0, 0, NULL, NULL, NULL);
}
}
free(svcaddr->buf);
free(svcaddr);
return (cl);
}
/*
* Generic client creation: returns client handle.
* Default options are set, which the user can
* change using the rpc equivalent of _ioctl()'s : clnt_control().
* If fd is RPC_ANYFD, it will be opened using nconf.
* It will be bound if not so.
* If sizes are 0; appropriate defaults will be chosen.
*/
CLIENT *
clnt_tli_create(const SOCKET fd_in, const struct netconfig *nconf,
struct netbuf *svcaddr, const rpcprog_t prog, const rpcvers_t vers,
const uint sendsz, const uint recvsz,
int (*callback_xdr)(void *, void *),
int (*callback_function)(void *, void *, void **),
void *callback_args)
{
CLIENT *cl; /* client handle */
bool_t madefd = FALSE; /* whether fd opened here */
long servtype;
BOOL one = TRUE;
struct __rpc_sockinfo si;
extern int __rpc_minfd;
SOCKET fd = fd_in;
if (fd == RPC_ANYFD) {
if (nconf == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
fd = __rpc_nconf2fd(nconf);
if (fd == INVALID_SOCKET)
goto err;
#if 0
if (fd < __rpc_minfd)
fd = __rpc_raise_fd(fd);
#endif
madefd = TRUE;
servtype = nconf->nc_semantics;
bindresvport(fd, NULL);
if (!__rpc_fd2sockinfo(fd, &si))
goto err;
} else {
if (!__rpc_fd2sockinfo(fd, &si))
goto err;
servtype = __rpc_socktype2seman(si.si_socktype);
if (servtype == -1) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
}
if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
rpc_createerr.cf_stat = RPC_UNKNOWNHOST; /* XXX */
goto err1;
}
switch (servtype) {
case NC_TPI_COTS:
cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz,
callback_xdr, callback_function, callback_args);
break;
case NC_TPI_COTS_ORD:
if (nconf &&
((strcmp(nconf->nc_protofmly, "inet") == 0) ||
(strcmp(nconf->nc_protofmly, "inet6") == 0))) {
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one,
sizeof (one));
}
cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz,
callback_xdr, callback_function, callback_args);
break;
case NC_TPI_CLTS:
cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
break;
default:
goto err;
}
if (cl == NULL)
goto err1; /* borrow errors from clnt_dg/vc creates */
if (nconf) {
cl->cl_netid = strdup(nconf->nc_netid);
cl->cl_tp = strdup(nconf->nc_device);
} else {
cl->cl_netid = "";
cl->cl_tp = "";
}
if (madefd) {
(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
/* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */
};
return (cl);
err:
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
err1: if (madefd)
(void)closesocket(fd);
return (NULL);
}
#if 0 /* WINDOWS */
/*
* To avoid conflicts with the "magic" file descriptors (0, 1, and 2),
* we try to not use them. The __rpc_raise_fd() routine will dup
* a descriptor to a higher value. If we fail to do it, we continue
* to use the old one (and hope for the best).
*/
int __rpc_minfd = 3;
int
__rpc_raise_fd(int fd)
{
int nfd;
if (fd >= __rpc_minfd)
return (fd);
if ((nfd = fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
return (fd);
if (fsync(nfd) == -1) {
closesocket(nfd);
return (fd);
}
if (closesocket(fd) == -1) {
/* this is okay, we will syslog an error, then use the new fd */
(void) syslog(LOG_ERR,
"could not close() fd %d; mem & fd leak", fd);
}
return (nfd);
}
#endif

339
libtirpc/src/clnt_perror.c Normal file
View file

@ -0,0 +1,339 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
#include <sys/cdefs.h>
*/
/*
* clnt_perror.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
#include <wintirpc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
static char *buf;
static char *_buf(void);
static char *auth_errmsg(enum auth_stat);
#define CLNT_PERROR_BUFLEN 256
static char *
_buf()
{
if (buf == 0)
buf = (char *)malloc(CLNT_PERROR_BUFLEN);
return (buf);
}
/*
* Print reply error info
*/
char *
clnt_sperror(rpch, s)
CLIENT *rpch;
const char *s;
{
struct rpc_err e;
char *err;
char *str;
char *strstart;
size_t len, i;
if (rpch == NULL || s == NULL)
return(0);
str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
if (str == 0)
return (0);
len = CLNT_PERROR_BUFLEN;
strstart = str;
CLNT_GETERR(rpch, &e);
if (snprintf(str, len, "%s: ", s) > 0) {
i = strlen(str);
str += i;
len -= i;
}
(void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
i = strlen(str);
str += i;
len -= i;
switch (e.re_status) {
case RPC_SUCCESS:
case RPC_CANTENCODEARGS:
case RPC_CANTDECODERES:
case RPC_TIMEDOUT:
case RPC_PROGUNAVAIL:
case RPC_PROCUNAVAIL:
case RPC_CANTDECODEARGS:
case RPC_SYSTEMERROR:
case RPC_UNKNOWNHOST:
case RPC_UNKNOWNPROTO:
case RPC_PMAPFAILURE:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
break;
case RPC_CANTSEND:
case RPC_CANTRECV:
snprintf(str, len, "; errno = %s", strerror(e.re_errno));
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_VERSMISMATCH:
snprintf(str, len, "; low version = %u, high version = %u",
e.re_vers.low, e.re_vers.high);
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_AUTHERROR:
err = auth_errmsg(e.re_why);
snprintf(str, len, "; why = ");
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
if (err != NULL) {
snprintf(str, len, "%s",err);
} else {
snprintf(str, len,
"(unknown authentication error - %d)",
(int) e.re_why);
}
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_PROGVERSMISMATCH:
snprintf(str, len, "; low version = %u, high version = %u",
e.re_vers.low, e.re_vers.high);
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
break;
default: /* unknown */
snprintf(str, len, "; s1 = %u, s2 = %u",
e.re_lb.s1, e.re_lb.s2);
i = strlen(str);
if (i > 0) {
str += i;
len -= i;
}
break;
}
strstart[CLNT_PERROR_BUFLEN-1] = '\0';
return(strstart) ;
}
void
clnt_perror(rpch, s)
CLIENT *rpch;
const char *s;
{
if (rpch == NULL || s == NULL)
return;
(void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
}
static const char *const rpc_errlist[] = {
"RPC: Success", /* 0 - RPC_SUCCESS */
"RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */
"RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */
"RPC: Unable to send", /* 3 - RPC_CANTSEND */
"RPC: Unable to receive", /* 4 - RPC_CANTRECV */
"RPC: Timed out", /* 5 - RPC_TIMEDOUT */
"RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */
"RPC: Authentication error", /* 7 - RPC_AUTHERROR */
"RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */
"RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */
"RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */
"RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */
"RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */
"RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */
"RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */
"RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */
"RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */
"RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */
};
/*
* This interface for use by clntrpc
*/
char *
clnt_sperrno(stat)
enum clnt_stat stat;
{
unsigned int errnum = stat;
if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
/* LINTED interface problem */
return (char *)rpc_errlist[errnum];
return ("RPC: (unknown error code)");
}
void
clnt_perrno(num)
enum clnt_stat num;
{
(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
}
char *
clnt_spcreateerror(s)
const char *s;
{
char *str, *err;
size_t len, i;
if (s == NULL)
return(0);
str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
if (str == 0)
return(0);
len = CLNT_PERROR_BUFLEN;
snprintf(str, len, "%s: ", s);
i = strlen(str);
if (i > 0)
len -= i;
(void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
switch (rpc_createerr.cf_stat) {
case RPC_PMAPFAILURE:
(void) strncat(str, " - ", len - 1);
err = clnt_sperrno(rpc_createerr.cf_error.re_status);
if (err)
(void) strncat(str, err+5, len-5);
switch(rpc_createerr.cf_error.re_status) {
case RPC_CANTSEND:
case RPC_CANTRECV:
i = strlen(str);
len -= i;
snprintf(str+i, len, ": errno %d (%s)",
rpc_createerr.cf_error.re_errno,
strerror(rpc_createerr.cf_error.re_errno));
break;
default:
break;
}
break;
case RPC_SYSTEMERROR:
(void)strncat(str, " - ", len - 1);
(void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
len - 4);
break;
case RPC_CANTSEND:
case RPC_CANTDECODERES:
case RPC_CANTENCODEARGS:
case RPC_SUCCESS:
case RPC_UNKNOWNPROTO:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
case RPC_UNKNOWNHOST:
case RPC_CANTDECODEARGS:
case RPC_PROCUNAVAIL:
case RPC_PROGVERSMISMATCH:
case RPC_PROGUNAVAIL:
case RPC_AUTHERROR:
case RPC_VERSMISMATCH:
case RPC_TIMEDOUT:
case RPC_CANTRECV:
default:
break;
}
str[CLNT_PERROR_BUFLEN-1] = '\0';
return (str);
}
void
clnt_pcreateerror(s)
const char *s;
{
if (s == NULL)
return;
(void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
}
static const char *const auth_errlist[] = {
"Authentication OK", /* 0 - AUTH_OK */
"Invalid client credential", /* 1 - AUTH_BADCRED */
"Server rejected credential", /* 2 - AUTH_REJECTEDCRED */
"Invalid client verifier", /* 3 - AUTH_BADVERF */
"Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */
"Client credential too weak", /* 5 - AUTH_TOOWEAK */
"Invalid server verifier", /* 6 - AUTH_INVALIDRESP */
"Failed (unspecified error)" /* 7 - AUTH_FAILED */
};
static char *
auth_errmsg(stat)
enum auth_stat stat;
{
unsigned int errnum = stat;
if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
/* LINTED interface problem */
return (char *)auth_errlist[errnum];
return(NULL);
}

306
libtirpc/src/clnt_raw.c Normal file
View file

@ -0,0 +1,306 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* clnt_raw.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Memory based rpc for simple testing and timing.
* Interface to create an rpc client and server in the same process.
* This lets us similate rpc and get round trip overhead, without
* any interference from the kernel.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <assert.h>
//#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
#include <rpc/raw.h>
extern mutex_t clntraw_lock;
#define MCALL_MSG_SIZE 24
/*
* This is the "network" we will be moving stuff over.
*/
static struct clntraw_private {
CLIENT client_object;
XDR xdr_stream;
char *_raw_buf;
union {
struct rpc_msg mashl_rpcmsg;
char mashl_callmsg[MCALL_MSG_SIZE];
} u;
u_int mcnt;
} *clntraw_private;
static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
xdrproc_t, void *, struct timeval);
static void clnt_raw_geterr(CLIENT *, struct rpc_err *);
static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *);
static void clnt_raw_abort(CLIENT *);
static bool_t clnt_raw_control(CLIENT *, u_int, void *);
static void clnt_raw_destroy(CLIENT *);
static struct clnt_ops *clnt_raw_ops(void);
/*
* Create a client handle for memory based rpc.
*/
CLIENT *
clnt_raw_create(prog, vers)
rpcprog_t prog;
rpcvers_t vers;
{
struct clntraw_private *clp;
struct rpc_msg call_msg;
XDR *xdrs;
CLIENT *client;
mutex_lock(&clntraw_lock);
clp = clntraw_private;
if (clp == NULL) {
clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
if (clp == NULL) {
mutex_unlock(&clntraw_lock);
return NULL;
}
if (__rpc_rawcombuf == NULL)
__rpc_rawcombuf =
(char *)calloc(UDPMSGSIZE, sizeof (char));
clp->_raw_buf = __rpc_rawcombuf;
clntraw_private = clp;
}
xdrs = &clp->xdr_stream;
client = &clp->client_object;
/*
* pre-serialize the static part of the call msg and stash it away
*/
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
/* XXX: prog and vers have been long historically :-( */
call_msg.rm_call.cb_prog = (u_int32_t)prog;
call_msg.rm_call.cb_vers = (u_int32_t)vers;
xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
if (! xdr_callhdr(xdrs, &call_msg))
//warnx("clntraw_create - Fatal header serialization error.");
clp->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
/*
* Set xdrmem for client/server shared buffer
*/
xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
/*
* create client handle
*/
client->cl_ops = clnt_raw_ops();
client->cl_auth = authnone_create();
mutex_unlock(&clntraw_lock);
return (client);
}
/* ARGSUSED */
static enum clnt_stat
clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
CLIENT *h;
rpcproc_t proc;
xdrproc_t xargs;
void *argsp;
xdrproc_t xresults;
void *resultsp;
struct timeval timeout;
{
struct clntraw_private *clp = clntraw_private;
XDR *xdrs = &clp->xdr_stream;
struct rpc_msg msg;
enum clnt_stat status;
struct rpc_err error;
assert(h != NULL);
mutex_lock(&clntraw_lock);
if (clp == NULL) {
mutex_unlock(&clntraw_lock);
return (RPC_FAILED);
}
mutex_unlock(&clntraw_lock);
call_again:
/*
* send request
*/
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, 0);
clp->u.mashl_rpcmsg.rm_xid ++ ;
if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
(! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp))) {
return (RPC_CANTENCODEARGS);
}
(void)XDR_GETPOS(xdrs); /* called just to cause overhead */
/*
* We have to call server input routine here because this is
* all going on in one process. Yuk.
*/
svc_getreq_common(FD_SETSIZE);
/*
* get results
*/
xdrs->x_op = XDR_DECODE;
XDR_SETPOS(xdrs, 0);
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = resultsp;
msg.acpted_rply.ar_results.proc = xresults;
if (! xdr_replymsg(xdrs, &msg)) {
/*
* It's possible for xdr_replymsg() to fail partway
* through its attempt to decode the result from the
* server. If this happens, it will leave the reply
* structure partially populated with dynamically
* allocated memory. (This can happen if someone uses
* clntudp_bufcreate() to create a CLIENT handle and
* specifies a receive buffer size that is too small.)
* This memory must be free()ed to avoid a leak.
*/
int op = xdrs->x_op;
xdrs->x_op = XDR_FREE;
xdr_replymsg(xdrs, &msg);
xdrs->x_op = op;
return (RPC_CANTDECODERES);
}
_seterr_reply(&msg, &error);
status = error.re_status;
if (status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
status = RPC_AUTHERROR;
}
} /* end successful completion */
else {
if (AUTH_REFRESH(h->cl_auth, &msg))
goto call_again;
} /* end of unsuccessful completion */
if (status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
status = RPC_AUTHERROR;
}
if (msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
}
}
return (status);
}
/*ARGSUSED*/
static void
clnt_raw_geterr(cl, err)
CLIENT *cl;
struct rpc_err *err;
{
}
/* ARGSUSED */
static bool_t
clnt_raw_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
void *res_ptr;
{
struct clntraw_private *clp = clntraw_private;
XDR *xdrs = &clp->xdr_stream;
bool_t rval;
mutex_lock(&clntraw_lock);
if (clp == NULL) {
rval = (bool_t) RPC_FAILED;
mutex_unlock(&clntraw_lock);
return (rval);
}
mutex_unlock(&clntraw_lock);
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
/*ARGSUSED*/
static void
clnt_raw_abort(cl)
CLIENT *cl;
{
}
/*ARGSUSED*/
static bool_t
clnt_raw_control(cl, ui, str)
CLIENT *cl;
u_int ui;
void *str;
{
return (FALSE);
}
/*ARGSUSED*/
static void
clnt_raw_destroy(cl)
CLIENT *cl;
{
}
static struct clnt_ops *
clnt_raw_ops()
{
static struct clnt_ops ops;
extern mutex_t ops_lock;
/* VARIABLES PROTECTED BY ops_lock: ops */
mutex_lock(&ops_lock);
if (ops.cl_call == NULL) {
ops.cl_call = clnt_raw_call;
ops.cl_abort = clnt_raw_abort;
ops.cl_geterr = clnt_raw_geterr;
ops.cl_freeres = clnt_raw_freeres;
ops.cl_destroy = clnt_raw_destroy;
ops.cl_control = clnt_raw_control;
}
mutex_unlock(&ops_lock);
return (&ops);
}

180
libtirpc/src/clnt_simple.c Normal file
View file

@ -0,0 +1,180 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
//#include <sys/cdefs.h>
/*
* clnt_simple.c
* Simplified front end to client rpc.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
//#include <sys/param.h>
#include <stdio.h>
#include <errno.h>
#include <rpc/rpc.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
//#include <unistd.h>
#include <rpc/clnt.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#ifndef NETIDLEN
#define NETIDLEN 32
#endif
struct rpc_call_private {
int valid; /* Is this entry valid ? */
CLIENT *client; /* Client handle */
pid_t pid; /* process-id at moment of creation */
rpcprog_t prognum; /* Program */
rpcvers_t versnum; /* Version */
char host[MAXHOSTNAMELEN]; /* Servers host */
char nettype[NETIDLEN]; /* Network type */
};
static void rpc_call_destroy(void *);
static void
rpc_call_destroy(void *vp)
{
struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
if (rcp) {
if (rcp->client)
CLNT_DESTROY(rcp->client);
free(rcp);
}
}
/*
* This is the simplified interface to the client rpc layer.
* The client handle is not destroyed here and is reused for
* the future calls to same prog, vers, host and nettype combination.
*
* The total time available is 25 seconds.
*/
enum clnt_stat
rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
const char *host; /* host name */
rpcprog_t prognum; /* program number */
rpcvers_t versnum; /* version number */
rpcproc_t procnum; /* procedure number */
xdrproc_t inproc, outproc; /* in/out XDR procedures */
const char *in;
char *out; /* recv/send data */
const char *nettype; /* nettype */
{
struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
enum clnt_stat clnt_stat;
struct timeval timeout, tottimeout;
extern thread_key_t rpc_call_key;
extern mutex_t tsd_lock;
if (rpc_call_key == -1) {
mutex_lock(&tsd_lock);
if (rpc_call_key == -1)
thr_keycreate(&rpc_call_key, rpc_call_destroy);
mutex_unlock(&tsd_lock);
}
rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
if (rcp == NULL) {
rcp = malloc(sizeof (*rcp));
if (rcp == NULL) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
return (rpc_createerr.cf_stat);
}
thr_setspecific(rpc_call_key, (void *) rcp);
rcp->valid = 0;
rcp->client = NULL;
}
if ((nettype == NULL) || (nettype[0] == 0))
nettype = "netpath";
if (!(rcp->valid && rcp->pid == getpid() &&
(rcp->prognum == prognum) &&
(rcp->versnum == versnum) &&
(!strcmp(rcp->host, host)) &&
(!strcmp(rcp->nettype, nettype)))) {
int fd;
rcp->valid = 0;
if (rcp->client)
CLNT_DESTROY(rcp->client);
/*
* Using the first successful transport for that type
*/
rcp->client = clnt_create(host, prognum, versnum, nettype);
rcp->pid = getpid();
if (rcp->client == NULL) {
return (rpc_createerr.cf_stat);
}
/*
* Set time outs for connectionless case. Do it
* unconditionally. Faster than doing a t_getinfo()
* and then doing the right thing.
*/
timeout.tv_usec = 0;
timeout.tv_sec = 5;
(void) CLNT_CONTROL(rcp->client,
CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
; // XXX fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
rcp->prognum = prognum;
rcp->versnum = versnum;
if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
(strlen(nettype) < (size_t)NETIDLEN)) {
(void) strcpy(rcp->host, host);
(void) strcpy(rcp->nettype, nettype);
rcp->valid = 1;
} else {
rcp->valid = 0;
}
} /* else reuse old client */
tottimeout.tv_sec = 25;
tottimeout.tv_usec = 0;
/* LINTED const castaway */
clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
outproc, out, tottimeout);
/*
* if call failed, empty cache
*/
if (clnt_stat != RPC_SUCCESS)
rcp->valid = 0;
return (clnt_stat);
}

1000
libtirpc/src/clnt_vc.c Normal file

File diff suppressed because it is too large Load diff

101
libtirpc/src/crypt_client.c Normal file
View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 1996
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
#include <wintirpc.h>
//#include <err.h>
#include <sys/types.h>
#include <rpc/des_crypt.h>
#include <rpc/des.h>
#include <string.h>
#include <rpcsvc/crypt.h>
#include <netconfig.h>
int
_des_crypt_call(buf, len, dparms)
char *buf;
int len;
struct desparams *dparms;
{
CLIENT *clnt;
desresp *result_1;
desargs des_crypt_1_arg;
struct netconfig *nconf;
void *localhandle;
int stat;
nconf = NULL;
localhandle = setnetconfig();
while ((nconf = getnetconfig(localhandle)) != NULL) {
if (nconf->nc_protofmly != NULL &&
strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
break;
}
if (nconf == NULL) {
//warnx("getnetconfig: %s", nc_sperror());
return(DESERR_HWERROR);
}
clnt = clnt_tp_create(NULL, CRYPT_PROG, CRYPT_VERS, nconf);
if (clnt == (CLIENT *) NULL) {
endnetconfig(localhandle);
return(DESERR_HWERROR);
}
endnetconfig(localhandle);
des_crypt_1_arg.desbuf.desbuf_len = len;
des_crypt_1_arg.desbuf.desbuf_val = buf;
des_crypt_1_arg.des_dir = dparms->des_dir;
des_crypt_1_arg.des_mode = dparms->des_mode;
bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);
result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
if (result_1 == (desresp *) NULL) {
clnt_destroy(clnt);
return(DESERR_HWERROR);
}
stat = result_1->stat;
if (result_1->stat == DESERR_NONE ||
result_1->stat == DESERR_NOHWDEVICE) {
bcopy(result_1->desbuf.desbuf_val, buf, len);
bcopy(result_1->des_ivec, dparms->des_ivec, 8);
}
clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1);
clnt_destroy(clnt);
return(stat);
}

155
libtirpc/src/des_crypt.c Normal file
View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* des_crypt.c, DES encryption library routines
* Copyright (C) 1986, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
#include <rpc/types.h>
#include <rpc/des_crypt.h>
#include <rpc/des.h>
#if 0
#ifndef lint
static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
#endif
#endif
//#include <sys/cdefs.h>
static int common_crypt( char *, char *, unsigned, unsigned, struct desparams * );
int (*__des_crypt_LOCAL)() = 0;
extern int _des_crypt_call(char *, int, struct desparams *);
/*
* Copy 8 bytes
*/
#define COPY8(src, dst) { \
char *a = (char *) dst; \
char *b = (char *) src; \
*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
}
/*
* Copy multiple of 8 bytes
*/
#define DESCOPY(src, dst, len) { \
char *a = (char *) dst; \
char *b = (char *) src; \
int i; \
for (i = (int) len; i > 0; i -= 8) { \
*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
} \
}
/*
* CBC mode encryption
*/
int
cbc_crypt(key, buf, len, mode, ivec)
char *key;
char *buf;
unsigned len;
unsigned mode;
char *ivec;
{
int err;
struct desparams dp;
#ifdef BROKEN_DES
dp.UDES.UDES_buf = buf;
dp.des_mode = ECB;
#else
dp.des_mode = CBC;
#endif
COPY8(ivec, dp.des_ivec);
err = common_crypt(key, buf, len, mode, &dp);
COPY8(dp.des_ivec, ivec);
return(err);
}
/*
* ECB mode encryption
*/
int
ecb_crypt(key, buf, len, mode)
char *key;
char *buf;
unsigned len;
unsigned mode;
{
struct desparams dp;
#ifdef BROKEN_DES
dp.UDES.UDES_buf = buf;
dp.des_mode = CBC;
#else
dp.des_mode = ECB;
#endif
return(common_crypt(key, buf, len, mode, &dp));
}
/*
* Common code to cbc_crypt() & ecb_crypt()
*/
static int
common_crypt(key, buf, len, mode, desp)
char *key;
char *buf;
unsigned len;
unsigned mode;
struct desparams *desp;
{
int desdev;
if ((len % 8) != 0 || len > DES_MAXDATA) {
return(DESERR_BADPARAM);
}
desp->des_dir =
((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
desdev = mode & DES_DEVMASK;
COPY8(key, desp->des_key);
/*
* software
*/
if (__des_crypt_LOCAL != NULL) {
if (!__des_crypt_LOCAL(buf, len, desp)) {
return (DESERR_HWERROR);
}
} else {
if (!_des_crypt_call(buf, len, desp)) {
return (DESERR_HWERROR);
}
}
return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
}

65
libtirpc/src/des_soft.c Normal file
View file

@ -0,0 +1,65 @@
//#include <sys/cdefs.h>
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Table giving odd parity in the low bit for ASCII characters
*/
static char partab[128] = {
0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
};
/*
* Add odd parity to low bit of 8 byte key
*/
void
des_setparity(p)
char *p;
{
int i;
for (i = 0; i < 8; i++) {
*p = partab[*p & 0x7f];
p++;
}
}

62
libtirpc/src/epoll_sub.c Normal file
View file

@ -0,0 +1,62 @@
/*
* Copyright 2003 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <wintirpc.h>
#ifndef _WIN32
#include <stdint.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/epoll.h>
#include <unistd.h>
/*Paramètres du syscall - Attention spécifique hardware */
#define __NR_epoll_create 254
#define __NR_epoll_ctl 255
#define __NR_epoll_wait 256
int
epoll_create(int size)
{
return (syscall(__NR_epoll_create, size));
}
int
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
}
int
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
{
return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
}
#endif

700
libtirpc/src/getnetconfig.c Normal file
View file

@ -0,0 +1,700 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1989 by Sun Microsystems, Inc.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
//#include <sys/cdefs.h>
#include <stdio.h>
#include <errno.h>
#include <netconfig.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
//#include <unistd.h>
#include "rpc_com.h"
// XXX FIXME - this is in wintirpc.c, but that is not currently built
static void wintirpc_debug(char *fmt, ...)
{
return;
}
/*
* The five library routines in this file provide application access to the
* system network configuration database, /etc/netconfig. In addition to the
* netconfig database and the routines for accessing it, the environment
* variable NETPATH and its corresponding routines in getnetpath.c may also be
* used to specify the network transport to be used.
*/
/*
* netconfig errors
*/
#define NC_NONETCONFIG ENOENT
#define NC_NOMEM ENOMEM
#define NC_NOTINIT EINVAL /* setnetconfig was not called first */
#define NC_BADFILE EBADF /* format for netconfig file is bad */
#define NC_NOTFOUND WSAENOPROTOOPT /* specified netid was not found */
/*
* semantics as strings (should be in netconfig.h)
*/
#define NC_TPI_CLTS_S "tpi_clts"
#define NC_TPI_COTS_S "tpi_cots"
#define NC_TPI_COTS_ORD_S "tpi_cots_ord"
#define NC_TPI_RAW_S "tpi_raw"
/*
* flags as characters (also should be in netconfig.h)
*/
#define NC_NOFLAG_C '-'
#define NC_VISIBLE_C 'v'
#define NC_BROADCAST_C 'b'
/*
* Character used to indicate there is no name-to-address lookup library
*/
#define NC_NOLOOKUP "-"
static const char * const _nc_errors[] = {
"Netconfig database not found",
"Not enough memory",
"Not initialized",
"Netconfig database has invalid format",
"Netid not found in netconfig database"
};
struct netconfig_info {
int eof; /* all entries has been read */
int ref; /* # of times setnetconfig() has been called */
struct netconfig_list *head; /* head of the list */
struct netconfig_list *tail; /* last of the list */
};
struct netconfig_list {
char *linep; /* hold line read from netconfig */
struct netconfig *ncp;
struct netconfig_list *next;
};
struct netconfig_vars {
int valid; /* token that indicates a valid netconfig_vars */
int flag; /* first time flag */
struct netconfig_list *nc_configs; /* pointer to the current netconfig entry */
};
#define NC_VALID 0xfeed
#define NC_STORAGE 0xf00d
#define NC_INVALID 0
static int *__nc_error(void);
static int parse_ncp(char *, struct netconfig *);
static struct netconfig *dup_ncp(struct netconfig *);
static FILE *nc_file; /* for netconfig db */
static struct netconfig_info ni = { 0, 0, NULL, NULL};
#define MAXNETCONFIGLINE 1000
static int *
__nc_error()
{
extern mutex_t nc_lock;
extern thread_key_t nc_key;
static int nc_error = 0;
int error, *nc_addr;
/*
* Use the static `nc_error' if we are the main thread
* (including non-threaded programs), or if an allocation
* fails.
*/
if (nc_key == -1) {
error = 0;
mutex_lock(&nc_lock);
if (nc_key == -1)
error = nc_key = TlsAlloc(); //thr_keycreate(&nc_key, free);
mutex_unlock(&nc_lock);
if (error == TLS_OUT_OF_INDEXES)
return (&nc_error);
}
if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
nc_addr = (int *)malloc(sizeof (int *));
if (thr_setspecific(nc_key, (void *) nc_addr) == 0) {
if (nc_addr)
free(nc_addr);
return (&nc_error);
}
*nc_addr = 0;
}
return (nc_addr);
}
#define nc_error (*(__nc_error()))
/*
* A call to setnetconfig() establishes a /etc/netconfig "session". A session
* "handle" is returned on a successful call. At the start of a session (after
* a call to setnetconfig()) searches through the /etc/netconfig database will
* proceed from the start of the file. The session handle must be passed to
* getnetconfig() to parse the file. Each call to getnetconfig() using the
* current handle will process one subsequent entry in /etc/netconfig.
* setnetconfig() must be called before the first call to getnetconfig().
* (Handles are used to allow for nested calls to setnetpath()).
*
* A new session is established with each call to setnetconfig(), with a new
* handle being returned on each call. Previously established sessions remain
* active until endnetconfig() is called with that session's handle as an
* argument.
*
* setnetconfig() need *not* be called before a call to getnetconfigent().
* setnetconfig() returns a NULL pointer on failure (for example, if
* the netconfig database is not present).
*/
void *
setnetconfig()
{
struct netconfig_vars *nc_vars;
if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
(struct netconfig_vars))) == NULL) {
return(NULL);
}
/*
* For multiple calls, i.e. nc_file is not NULL, we just return the
* handle without reopening the netconfig db.
*/
ni.ref++;
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
nc_vars->valid = NC_VALID;
nc_vars->flag = 0;
nc_vars->nc_configs = ni.head;
return ((void *)nc_vars);
}
ni.ref--;
nc_error = NC_NONETCONFIG;
free(nc_vars);
return (NULL);
}
/*
* When first called, getnetconfig() returns a pointer to the first entry in
* the netconfig database, formatted as a struct netconfig. On each subsequent
* call, getnetconfig() returns a pointer to the next entry in the database.
* getnetconfig() can thus be used to search the entire netconfig file.
* getnetconfig() returns NULL at end of file.
*/
struct netconfig *
getnetconfig(handlep)
void *handlep;
{
struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
char *stringp; /* tmp string pointer */
struct netconfig_list *list;
struct netconfig *np;
/*
* Verify that handle is valid
*/
if (ncp == NULL || nc_file == NULL) {
nc_error = NC_NOTINIT;
return (NULL);
}
switch (ncp->valid) {
case NC_VALID:
/*
* If entry has already been read into the list,
* we return the entry in the linked list.
* If this is the first time call, check if there are any entries in
* linked list. If no entries, we need to read the netconfig db.
* If we have been here and the next entry is there, we just return
* it.
*/
if (ncp->flag == 0) { /* first time */
ncp->flag = 1;
ncp->nc_configs = ni.head;
if (ncp->nc_configs != NULL) /* entry already exist */
return(ncp->nc_configs->ncp);
}
else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
ncp->nc_configs = ncp->nc_configs->next;
return(ncp->nc_configs->ncp);
}
/*
* If we cannot find the entry in the list and is end of file,
* we give up.
*/
if (ni.eof == 1)
return(NULL);
break;
default:
nc_error = NC_NOTINIT;
return (NULL);
}
stringp = (char *) malloc(MAXNETCONFIGLINE);
if (stringp == NULL)
return (NULL);
#ifdef MEM_CHK
if (malloc_verify() == 0) {
fprintf(stderr, "memory heap corrupted in getnetconfig\n");
exit(1);
}
#endif
/*
* Read a line from netconfig file.
*/
do {
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
free(stringp);
ni.eof = 1;
return (NULL);
}
} while (*stringp == '#');
list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
if (list == NULL) {
free(stringp);
return(NULL);
}
np = (struct netconfig *) malloc(sizeof (struct netconfig));
if (np == NULL) {
free(stringp);
free(list);
return(NULL);
}
list->ncp = np;
list->next = NULL;
list->ncp->nc_lookups = NULL;
list->linep = stringp;
wintirpc_debug("%s: before parse: &list->linep %p, list->linep %p, stringp %p\n", __FUNCTION__, &list->linep, list->linep, stringp);
if (parse_ncp(stringp, list->ncp) == -1) {
free(stringp);
free(np);
free(list);
return (NULL);
} else {
wintirpc_debug("%s: after parse: list->linep %p, stringp %p\n", __FUNCTION__, list->linep, stringp);
/*
* If this is the first entry that's been read, it is the head of
* the list. If not, put the entry at the end of the list.
* Reposition the current pointer of the handle to the last entry
* in the list.
*/
if (ni.head == NULL) { /* first entry */
ni.head = ni.tail = list;
}
else {
ni.tail->next = list;
ni.tail = ni.tail->next;
}
ncp->nc_configs = ni.tail;
return(ni.tail->ncp);
}
}
/*
* endnetconfig() may be called to "unbind" or "close" the netconfig database
* when processing is complete, releasing resources for reuse. endnetconfig()
* may not be called before setnetconfig(). endnetconfig() returns 0 on
* success and -1 on failure (for example, if setnetconfig() was not called
* previously).
*/
int
endnetconfig(handlep)
void *handlep;
{
struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
struct netconfig_list *q, *p;
/*
* Verify that handle is valid
*/
if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
nc_handlep->valid != NC_STORAGE)) {
nc_error = NC_NOTINIT;
return (-1);
}
/*
* Return 0 if anyone still needs it.
*/
nc_handlep->valid = NC_INVALID;
nc_handlep->flag = 0;
nc_handlep->nc_configs = NULL;
if (--ni.ref > 0) {
free(nc_handlep);
return(0);
}
/*
* Noone needs these entries anymore, then frees them.
* Make sure all info in netconfig_info structure has been reinitialized.
*/
q = p = ni.head;
ni.eof = ni.ref = 0;
ni.head = NULL;
ni.tail = NULL;
while (q) {
p = q->next;
if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
free(q->ncp);
free(q->linep);
free(q);
q = p;
}
free(nc_handlep);
fclose(nc_file);
nc_file = NULL;
return (0);
}
/*
* getnetconfigent(netid) returns a pointer to the struct netconfig structure
* corresponding to netid. It returns NULL if netid is invalid (that is, does
* not name an entry in the netconfig database). It returns NULL and sets
* errno in case of failure (for example, if the netconfig database cannot be
* opened).
*/
struct netconfig *
getnetconfigent(netid)
const char *netid;
{
FILE *file; /* NETCONFIG db's file pointer */
char *linep; /* holds current netconfig line */
char *stringp; /* temporary string pointer */
struct netconfig *ncp = NULL; /* returned value */
struct netconfig_list *list; /* pointer to cache list */
nc_error = NC_NOTFOUND; /* default error. */
if (netid == NULL || strlen(netid) == 0) {
return (NULL);
}
if (strcmp(netid, "unix") == 0) {
fprintf(stderr, "The local transport is called \"unix\" ");
fprintf(stderr, "in /etc/netconfig.\n");
fprintf(stderr, "Please change this to \"local\" manually ");
fprintf(stderr, "or run mergemaster(8).\n");
fprintf(stderr, "See UPDATING entry 20021216 for details.\n");
fprintf(stderr, "Continuing in 10 seconds\n\n");
fprintf(stderr, "This warning will be removed 20030301\n");
Sleep(10000); // sleep(10);
}
/*
* Look up table if the entries have already been read and parsed in
* getnetconfig(), then copy this entry into a buffer and return it.
* If we cannot find the entry in the current list and there are more
* entries in the netconfig db that has not been read, we then read the
* db and try find the match netid.
* If all the netconfig db has been read and placed into the list and
* there is no match for the netid, return NULL.
*/
if (ni.head != NULL) {
for (list = ni.head; list; list = list->next) {
if (strcmp(list->ncp->nc_netid, netid) == 0) {
return(dup_ncp(list->ncp));
}
}
if (ni.eof == 1) /* that's all the entries */
return(NULL);
}
if ((file = fopen(NETCONFIG, "r")) == NULL) {
nc_error = NC_NONETCONFIG;
return (NULL);
}
if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
fclose(file);
nc_error = NC_NOMEM;
return (NULL);
}
do {
ptrdiff_t len;
char *tmpp; /* tmp string pointer */
do {
if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
break;
}
} while (*stringp == '#');
if (stringp == NULL) { /* eof */
break;
}
if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */
nc_error = NC_BADFILE;
break;
}
if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */
strncmp(stringp, netid, (size_t)len) == 0) {
if ((ncp = (struct netconfig *)
malloc(sizeof (struct netconfig))) == NULL) {
break;
}
ncp->nc_lookups = NULL;
if (parse_ncp(linep, ncp) == -1) {
free(ncp);
ncp = NULL;
}
break;
}
} while (stringp != NULL);
if (ncp == NULL) {
free(linep);
}
fclose(file);
return(ncp);
}
/*
* freenetconfigent(netconfigp) frees the netconfig structure pointed to by
* netconfigp (previously returned by getnetconfigent()).
*/
void
freenetconfigent(netconfigp)
struct netconfig *netconfigp;
{
if (netconfigp != NULL) {
free(netconfigp->nc_netid); /* holds all netconfigp's strings */
if (netconfigp->nc_lookups != NULL)
free(netconfigp->nc_lookups);
free(netconfigp);
}
return;
}
/*
* Parse line and stuff it in a struct netconfig
* Typical line might look like:
* udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
*
* We return -1 if any of the tokens don't parse, or malloc fails.
*
* Note that we modify stringp (putting NULLs after tokens) and
* we set the ncp's string field pointers to point to these tokens within
* stringp.
*/
static int
parse_ncp(stringp, ncp)
char *stringp; /* string to parse */
struct netconfig *ncp; /* where to put results */
{
char *tokenp; /* for processing tokens */
char *lasts;
nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */
wintirpc_debug("%s: The last character being chopped is '%02x'\n", __FUNCTION__, stringp[strlen(stringp)-1]);
wintirpc_debug("%s: The string before chopping is '%s'\n", __FUNCTION__, stringp);
stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */
wintirpc_debug("%s: The last character after chopping is '%02x'\n", __FUNCTION__, stringp[strlen(stringp)-1]);
wintirpc_debug("%s: The string after chopping is '%s'\n", __FUNCTION__, stringp);
/* netid */
if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
return (-1);
}
/* semantics */
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
ncp->nc_semantics = NC_TPI_COTS_ORD;
else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
ncp->nc_semantics = NC_TPI_COTS;
else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
ncp->nc_semantics = NC_TPI_CLTS;
else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
ncp->nc_semantics = NC_TPI_RAW;
else
return (-1);
/* flags */
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
tokenp++) {
switch (*tokenp) {
case NC_NOFLAG_C:
break;
case NC_VISIBLE_C:
ncp->nc_flag |= NC_VISIBLE;
break;
case NC_BROADCAST_C:
ncp->nc_flag |= NC_BROADCAST;
break;
default:
return (-1);
}
}
/* protocol family */
if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
/* protocol name */
if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
/* network device */
if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
return (-1);
}
if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
ncp->nc_nlookups = 0;
ncp->nc_lookups = NULL;
} else {
char *cp; /* tmp string */
if (ncp->nc_lookups != NULL) /* from last visit */
free(ncp->nc_lookups);
/* preallocate one string pointer */
ncp->nc_lookups = (char **)malloc(sizeof (char *));
ncp->nc_nlookups = 0;
while ((cp = tokenp) != NULL) {
tokenp = _get_next_token(cp, ',');
ncp->nc_lookups[(size_t)ncp->nc_nlookups++] = cp;
ncp->nc_lookups = (char **)realloc(ncp->nc_lookups,
(size_t)(ncp->nc_nlookups+1) *sizeof(char *)); /* for next loop */
}
}
return (0);
}
/*
* Returns a string describing the reason for failure.
*/
char *
nc_sperror()
{
const char *message;
switch(nc_error) {
case NC_NONETCONFIG:
message = _nc_errors[0];
break;
case NC_NOMEM:
message = _nc_errors[1];
break;
case NC_NOTINIT:
message = _nc_errors[2];
break;
case NC_BADFILE:
message = _nc_errors[3];
break;
case NC_NOTFOUND:
message = _nc_errors[4];
break;
default:
message = "Unknown network selection error";
}
/* LINTED const castaway */
return ((char *)message);
}
/*
* Prints a message onto standard error describing the reason for failure.
*/
void
nc_perror(s)
const char *s;
{
fprintf(stderr, "%s: %s\n", s, nc_sperror());
}
/*
* Duplicates the matched netconfig buffer.
*/
static struct netconfig *
dup_ncp(ncp)
struct netconfig *ncp;
{
struct netconfig *p;
char *tmp;
u_int i;
if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
return(NULL);
if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
free(tmp);
return(NULL);
}
/*
* First we dup all the data from matched netconfig buffer. Then we
* adjust some of the member pointer to a pre-allocated buffer where
* contains part of the data.
* To follow the convention used in parse_ncp(), we store all the
* necessary information in the pre-allocated buffer and let each
* of the netconfig char pointer member point to the right address
* in the buffer.
*/
*p = *ncp;
p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
tmp = strchr(tmp, 0) + 1;
p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
tmp = strchr(tmp, 0) + 1;
p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
tmp = strchr(tmp, 0) + 1;
p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
if (p->nc_lookups == NULL) {
free(p->nc_netid);
return(NULL);
}
for (i=0; i < p->nc_nlookups; i++) {
tmp = strchr(tmp, 0) + 1;
p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
}
return(p);
}

264
libtirpc/src/getnetpath.c Normal file
View file

@ -0,0 +1,264 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* Copyright (c) 1989 by Sun Microsystems, Inc.
*/
//#include <sys/cdefs.h>
#include <wintirpc.h>
#include <stdio.h>
#include <errno.h>
#include <netconfig.h>
#include <stdlib.h>
#include <string.h>
//#include <syslog.h>
/*
* internal structure to keep track of a netpath "session"
*/
struct netpath_chain {
struct netconfig *ncp; /* an nconf entry */
struct netpath_chain *nchain_next; /* next nconf entry allocated */
};
struct netpath_vars {
int valid; /* token that indicates a valid netpath_vars */
void *nc_handlep; /* handle for current netconfig "session" */
char *netpath; /* pointer to current view-point in NETPATH */
char *netpath_start; /* pointer to start of our copy of NETPATH */
struct netpath_chain *ncp_list; /* list of nconfs allocated this session*/
};
#define NP_VALID 0xf00d
#define NP_INVALID 0
char *_get_next_token(char *, int);
/*
* A call to setnetpath() establishes a NETPATH "session". setnetpath()
* must be called before the first call to getnetpath(). A "handle" is
* returned to distinguish the session; this handle should be passed
* subsequently to getnetpath(). (Handles are used to allow for nested calls
* to setnetpath()).
* If setnetpath() is unable to establish a session (due to lack of memory
* resources, or the absence of the /etc/netconfig file), a NULL pointer is
* returned.
*/
void *
setnetpath()
{
struct netpath_vars *np_sessionp; /* this session's variables */
char *npp; /* NETPATH env variable */
#ifdef MEM_CHK
malloc_debug(1);
#endif
if ((np_sessionp =
(struct netpath_vars *)malloc(sizeof (struct netpath_vars))) == NULL) {
return (NULL);
}
if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
//syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
return (NULL);
}
np_sessionp->valid = NP_VALID;
np_sessionp->ncp_list = NULL;
if ((npp = getenv(NETPATH)) == NULL) {
np_sessionp->netpath = NULL;
} else {
(void) endnetconfig(np_sessionp->nc_handlep);/* won't need nc session*/
np_sessionp->nc_handlep = NULL;
if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL) {
free(np_sessionp);
return (NULL);
} else {
(void) strcpy(np_sessionp->netpath, npp);
}
}
np_sessionp->netpath_start = np_sessionp->netpath;
return ((void *)np_sessionp);
}
/*
* When first called, getnetpath() returns a pointer to the netconfig
* database entry corresponding to the first valid NETPATH component. The
* netconfig entry is formatted as a struct netconfig.
* On each subsequent call, getnetpath returns a pointer to the netconfig
* entry that corresponds to the next valid NETPATH component. getnetpath
* can thus be used to search the netconfig database for all networks
* included in the NETPATH variable.
* When NETPATH has been exhausted, getnetpath() returns NULL. It returns
* NULL and sets errno in case of an error (e.g., setnetpath was not called
* previously).
* getnetpath() silently ignores invalid NETPATH components. A NETPATH
* compnent is invalid if there is no corresponding entry in the netconfig
* database.
* If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
* were set to the sequence of default or visible networks in the netconfig
* database, in the order in which they are listed.
*/
struct netconfig *
getnetpath(handlep)
void *handlep;
{
struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
struct netconfig *ncp = NULL; /* temp. holds a netconfig session */
struct netpath_chain *chainp; /* holds chain of ncp's we alloc */
char *npp; /* holds current NETPATH */
if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
errno = EINVAL;
return (NULL);
}
if (np_sessionp->netpath_start == NULL) { /* NETPATH was not set */
do { /* select next visible network */
if (np_sessionp->nc_handlep == NULL) {
np_sessionp->nc_handlep = setnetconfig();
if (np_sessionp->nc_handlep == NULL) {
//syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
}
}
if ((ncp = getnetconfig(np_sessionp->nc_handlep)) == NULL) {
return(NULL);
}
} while ((ncp->nc_flag & NC_VISIBLE) == 0);
return (ncp);
}
/*
* Find first valid network ID in netpath.
*/
while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
np_sessionp->netpath = _get_next_token(npp, ':');
/*
* npp is a network identifier.
*/
if ((ncp = getnetconfigent(npp)) != NULL) {
chainp = (struct netpath_chain *) /* cobble alloc chain entry */
malloc(sizeof (struct netpath_chain));
chainp->ncp = ncp;
chainp->nchain_next = NULL;
if (np_sessionp->ncp_list == NULL) {
np_sessionp->ncp_list = chainp;
} else {
np_sessionp->ncp_list->nchain_next = chainp;
}
return (ncp);
}
/* couldn't find this token in the database; go to next one. */
}
return (NULL);
}
/*
* endnetpath() may be called to unbind NETPATH when processing is complete,
* releasing resources for reuse. It returns 0 on success and -1 on failure
* (e.g. if setnetpath() was not called previously.
*/
int
endnetpath(handlep)
void *handlep;
{
struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
struct netpath_chain *chainp, *lastp;
if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
errno = EINVAL;
return (-1);
}
if (np_sessionp->nc_handlep != NULL)
endnetconfig(np_sessionp->nc_handlep);
if (np_sessionp->netpath_start != NULL)
free(np_sessionp->netpath_start);
for (chainp = np_sessionp->ncp_list; chainp != NULL;
lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
freenetconfigent(chainp->ncp);
}
free(np_sessionp);
#ifdef MEM_CHK
if (malloc_verify() == 0) {
fprintf(stderr, "memory heap corrupted in endnetpath\n");
exit(1);
}
#endif
return (0);
}
/*
* Returns pointer to the rest-of-the-string after the current token.
* The token itself starts at arg, and we null terminate it. We return NULL
* if either the arg is empty, or if this is the last token.
*/
char *
_get_next_token(npp, token)
char *npp; /* string */
int token; /* char to parse string for */
{
char *cp; /* char pointer */
char *np; /* netpath pointer */
char *ep; /* escape pointer */
if ((cp = strchr(npp, token)) == NULL) {
return (NULL);
}
/*
* did find a token, but it might be escaped.
*/
if ((cp > npp) && (cp[-1] == '\\')) {
/* if slash was also escaped, carry on, otherwise find next token */
if ((cp > npp + 1) && (cp[-2] != '\\')) {
/* shift r-o-s onto the escaped token */
strcpy(&cp[-1], cp); /* XXX: overlapping string copy */
/*
* Do a recursive call.
* We don't know how many escaped tokens there might be.
*/
return (_get_next_token(cp, token));
}
}
*cp++ = '\0'; /* null-terminate token */
/* get rid of any backslash escapes */
ep = npp;
while ((np = strchr(ep, '\\')) != 0) {
if (np[1] == '\\')
np++;
strcpy(np, (ep = &np[1])); /* XXX: overlapping string copy */
}
return (cp); /* return ptr to r-o-s */
}

62
libtirpc/src/getpeereid.c Normal file
View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2001 Dima Dorfman.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
#include <wintirpc.h>
#include <rpc/types.h>
//#include <sys/param.h>
//#include <sys/socket.h>
//#include <sys/un.h>
#include <errno.h>
//#include <unistd.h>
#ifdef _WIN32
int
getpeereid(SOCKET s, uid_t *euid, gid_t *egid)
{
// XXX Need to figure out what to do here for Windows!
return -1;
}
#else
int
getpeereid(int s, uid_t *euid, gid_t *egid)
{
struct ucred uc;
socklen_t uclen;
int error;
uclen = sizeof(uc);
error = getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &uclen); /* SCM_CREDENTIALS */
if (error != 0)
return (error);
// if (uc.cr_version != XUCRED_VERSION)
// return (EINVAL);
*euid = uc.uid;
*egid = uc.gid;
return (0);
}
#endif

175
libtirpc/src/getpublickey.c Normal file
View file

@ -0,0 +1,175 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
#include <sys/cdefs.h>
*/
/*
* publickey.c
* Copyright (C) 1986, Sun Microsystems, Inc.
*/
/*
* Public key lookup routines
*/
#include <wintirpc.h>
#ifndef _WIN32
#include <stdio.h>
//#include <pwd.h>
#include <rpc/rpc.h>
#include <rpc/key_prot.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <string.h>
#include <stdlib.h>
#define PKFILE "/etc/publickey"
/*
* Hack to let ypserv/rpc.nisd use AUTH_DES.
*/
int (*__getpublickey_LOCAL)() = 0;
/*
* Get somebody's public key
*/
int
__getpublickey_real(netname, publickey)
char *netname;
char *publickey;
{
char lookup[3 * HEXKEYBYTES];
char *p;
if (publickey == NULL)
return (0);
if (!getpublicandprivatekey(netname, lookup))
return (0);
p = strchr(lookup, ':');
if (p == NULL) {
return (0);
}
*p = '\0';
(void) strncpy(publickey, lookup, HEXKEYBYTES);
publickey[HEXKEYBYTES] = '\0';
return (1);
}
/*
* reads the file /etc/publickey looking for a + to optionally go to the
* yellow pages
*/
int
getpublicandprivatekey(key, ret)
char *key;
char *ret;
{
char buf[1024]; /* big enough */
char *res;
FILE *fd;
char *mkey;
char *mval;
fd = fopen(PKFILE, "r");
if (fd == NULL)
return (0);
for (;;) {
res = fgets(buf, sizeof(buf), fd);
if (res == NULL) {
fclose(fd);
return (0);
}
if (res[0] == '#')
continue;
else if (res[0] == '+') {
#ifdef YP
char *PKMAP = "publickey.byname";
char *lookup;
char *domain;
int err;
int len;
err = yp_get_default_domain(&domain);
if (err) {
continue;
}
lookup = NULL;
err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len);
if (err) {
#ifdef DEBUG
fprintf(stderr, "match failed error %d\n", err);
#endif
continue;
}
lookup[len] = 0;
strcpy(ret, lookup);
fclose(fd);
free(lookup);
return (2);
#else /* YP */
#ifdef DEBUG
fprintf(stderr,
"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE);
#endif /* DEBUG */
continue;
#endif /* YP */
} else {
mkey = strsep(&res, "\t ");
if (mkey == NULL) {
fprintf(stderr,
"Bad record in %s -- %s", PKFILE, buf);
continue;
}
do {
mval = strsep(&res, " \t#\n");
} while (mval != NULL && !*mval);
if (mval == NULL) {
fprintf(stderr,
"Bad record in %s val problem - %s", PKFILE, buf);
continue;
}
if (strcmp(mkey, key) == 0) {
strcpy(ret, mval);
fclose(fd);
return (1);
}
}
}
}
int getpublickey(netname, publickey)
const char *netname;
char *publickey;
{
if (__getpublickey_LOCAL != NULL)
return(__getpublickey_LOCAL(netname, publickey));
else
return(__getpublickey_real(netname, publickey));
}
#endif /* ! _WIN32 */

311
libtirpc/src/getrpcent.c Normal file
View file

@ -0,0 +1,311 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>
#include <assert.h>
//#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
#include <libc_private.h>
/*
* Internet version.
*/
static struct rpcdata {
FILE *rpcf;
int stayopen;
#define MAXALIASES 35
char *rpc_aliases[MAXALIASES];
struct rpcent rpc;
char line[BUFSIZ+1];
#ifdef YP
char *domain;
char *current;
int currentlen;
#endif
} *rpcdata;
static struct rpcent *interpret(char *val, size_t len);
#ifdef YP
static int __yp_nomap = 0;
#endif /* YP */
#define RPCDB "/etc/rpc"
static struct rpcdata *_rpcdata(void);
static struct rpcdata *
_rpcdata()
{
struct rpcdata *d = rpcdata;
if (d == 0) {
d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
rpcdata = d;
}
return (d);
}
#ifdef GQ
struct rpcent *
getrpcbynumber(number)
int number;
{
#ifdef YP
int reason;
char adrstr[16];
#endif
struct rpcent *p;
struct rpcdata *d = _rpcdata();
if (d == 0)
return (0);
#ifdef YP
if (!__yp_nomap && _yp_check(&d->domain)) {
sprintf(adrstr, "%d", number);
reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr),
&d->current, &d->currentlen);
switch(reason) {
case 0:
break;
case YPERR_MAP:
__yp_nomap = 1;
goto no_yp;
break;
default:
return(0);
break;
}
d->current[d->currentlen] = '\0';
p = interpret(d->current, d->currentlen);
(void) free(d->current);
return p;
}
no_yp:
#endif /* YP */
setrpcent(0);
while ((p = getrpcent()) != NULL) {
if (p->r_number == number)
break;
}
endrpcent();
return (p);
}
struct rpcent *
getrpcbyname(name)
char *name;
{
struct rpcent *rpc = NULL;
char **rp;
assert(name != NULL);
setrpcent(0);
while ((rpc = getrpcent()) != NULL) {
if (strcmp(rpc->r_name, name) == 0)
goto done;
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
if (strcmp(*rp, name) == 0)
goto done;
}
}
done:
endrpcent();
return (rpc);
}
#endif /* GQ */
void
setrpcent(f)
int f;
{
struct rpcdata *d = _rpcdata();
if (d == 0)
return;
#ifdef YP
if (!__yp_nomap && _yp_check(NULL)) {
if (d->current)
free(d->current);
d->current = NULL;
d->currentlen = 0;
return;
}
__yp_nomap = 0;
#endif /* YP */
if (d->rpcf == NULL)
d->rpcf = fopen(RPCDB, "r");
else
rewind(d->rpcf);
d->stayopen |= f;
}
void
endrpcent()
{
struct rpcdata *d = _rpcdata();
if (d == 0)
return;
#ifdef YP
if (!__yp_nomap && _yp_check(NULL)) {
if (d->current && !d->stayopen)
free(d->current);
d->current = NULL;
d->currentlen = 0;
return;
}
__yp_nomap = 0;
#endif /* YP */
if (d->rpcf && !d->stayopen) {
fclose(d->rpcf);
d->rpcf = NULL;
}
}
struct rpcent *
getrpcent()
{
struct rpcdata *d = _rpcdata();
#ifdef YP
struct rpcent *hp;
int reason;
char *val = NULL;
int vallen;
#endif
if (d == 0)
return(NULL);
#ifdef YP
if (!__yp_nomap && _yp_check(&d->domain)) {
if (d->current == NULL && d->currentlen == 0) {
reason = yp_first(d->domain, "rpc.bynumber",
&d->current, &d->currentlen,
&val, &vallen);
} else {
reason = yp_next(d->domain, "rpc.bynumber",
d->current, d->currentlen,
&d->current, &d->currentlen,
&val, &vallen);
}
switch(reason) {
case 0:
break;
case YPERR_MAP:
__yp_nomap = 1;
goto no_yp;
break;
default:
return(0);
break;
}
val[vallen] = '\0';
hp = interpret(val, vallen);
(void) free(val);
return hp;
}
no_yp:
#endif /* YP */
if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
return (NULL);
/* -1 so there is room to append a \n below */
if (fgets(d->line, BUFSIZ - 1, d->rpcf) == NULL)
return (NULL);
return (interpret(d->line, strlen(d->line)));
}
static struct rpcent *
interpret(val, len)
char *val;
size_t len;
{
struct rpcdata *d = _rpcdata();
char *p;
char *cp, **q;
assert(val != NULL);
if (d == 0)
return (0);
(void) strncpy(d->line, val, BUFSIZ);
d->line[BUFSIZ] = '\0';
p = d->line;
p[len] = '\n';
if (*p == '#')
return (getrpcent());
cp = strpbrk(p, "#\n");
if (cp == NULL)
return (getrpcent());
*cp = '\0';
cp = strpbrk(p, " \t");
if (cp == NULL)
return (getrpcent());
*cp++ = '\0';
/* THIS STUFF IS INTERNET SPECIFIC */
d->rpc.r_name = d->line;
while (*cp == ' ' || *cp == '\t')
cp++;
d->rpc.r_number = atoi(cp);
q = d->rpc.r_aliases = d->rpc_aliases;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &(d->rpc_aliases[MAXALIASES - 1]))
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
return (&d->rpc);
}

67
libtirpc/src/getrpcport.c Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <sys/socket.h>
#include <assert.h>
//#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
int
getrpcport(host, prognum, versnum, proto)
char *host;
int prognum, versnum, proto;
{
struct sockaddr_in addr;
struct hostent *hp;
assert(host != NULL);
if ((hp = gethostbyname(host)) == NULL)
return (0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = 0;
if (hp->h_length > sizeof(addr))
hp->h_length = sizeof(addr);
memcpy(&addr.sin_addr.s_addr, hp->h_addr, (size_t)hp->h_length);
/* Inconsistent interfaces need casts! :-( */
return (pmap_getport(&addr, (u_long)prognum, (u_long)versnum,
(u_int)proto));
}

View file

@ -0,0 +1,44 @@
/* XXX NEED Copyright info */
#include <wintirpc.h>
#include < time.h >
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres /= 10; /*convert into microseconds*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}

466
libtirpc/src/key_call.c Normal file
View file

@ -0,0 +1,466 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
//#include <sys/cdefs.h>
/*
* key_call.c, Interface to keyserver
*
* setsecretkey(key) - set your secret key
* encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
* decryptsessionkey(agent, deskey) - decrypt ditto
* gendeskey(deskey) - generate a secure des key
*/
#ifndef _WIN32
#include <pthread.h>
#include <reentrant.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <rpc/rpc.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
#include <rpc/key_prot.h>
#include <string.h>
#include <netconfig.h>
#include <sys/utsname.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/fcntl.h>
#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
#define KEY_NRETRY 12 /* number of retries */
#ifdef DEBUG
#define debug(msg) (void) fprintf(stderr, "%s\n", msg);
#else
#define debug(msg)
#endif /* DEBUG */
/*
* Hack to allow the keyserver to use AUTH_DES (for authenticated
* NIS+ calls, for example). The only functions that get called
* are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
*
* The approach is to have the keyserver fill in pointers to local
* implementations of these functions, and to call those in key_call().
*/
cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
des_block *(*__key_gendes_LOCAL)() = 0;
static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *);
int
key_setsecret(secretkey)
const char *secretkey;
{
keystatus status;
if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf,
(void *)secretkey,
(xdrproc_t)xdr_keystatus, &status)) {
return (-1);
}
if (status != KEY_SUCCESS) {
debug("set status is nonzero");
return (-1);
}
return (0);
}
/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
* stored for the caller's effective uid; it returns 0 otherwise
*
* N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
* be using it, because it allows them to get the user's secret key.
*/
int
key_secretkey_is_set(void)
{
struct key_netstres kres;
memset((void*)&kres, 0, sizeof (kres));
if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_key_netstres, &kres) &&
(kres.status == KEY_SUCCESS) &&
(kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
/* avoid leaving secret key in memory */
memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
return (1);
}
return (0);
}
int
key_encryptsession_pk(remotename, remotekey, deskey)
char *remotename;
netobj *remotekey;
des_block *deskey;
{
cryptkeyarg2 arg;
cryptkeyres res;
arg.remotename = remotename;
arg.remotekey = *remotekey;
arg.deskey = *deskey;
if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
(xdrproc_t)xdr_cryptkeyres, &res)) {
return (-1);
}
if (res.status != KEY_SUCCESS) {
debug("encrypt status is nonzero");
return (-1);
}
*deskey = res.cryptkeyres_u.deskey;
return (0);
}
int
key_decryptsession_pk(remotename, remotekey, deskey)
char *remotename;
netobj *remotekey;
des_block *deskey;
{
cryptkeyarg2 arg;
cryptkeyres res;
arg.remotename = remotename;
arg.remotekey = *remotekey;
arg.deskey = *deskey;
if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
(xdrproc_t)xdr_cryptkeyres, &res)) {
return (-1);
}
if (res.status != KEY_SUCCESS) {
debug("decrypt status is nonzero");
return (-1);
}
*deskey = res.cryptkeyres_u.deskey;
return (0);
}
int
key_encryptsession(remotename, deskey)
const char *remotename;
des_block *deskey;
{
cryptkeyarg arg;
cryptkeyres res;
arg.remotename = (char *) remotename;
arg.deskey = *deskey;
if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
(xdrproc_t)xdr_cryptkeyres, &res)) {
return (-1);
}
if (res.status != KEY_SUCCESS) {
debug("encrypt status is nonzero");
return (-1);
}
*deskey = res.cryptkeyres_u.deskey;
return (0);
}
int
key_decryptsession(remotename, deskey)
const char *remotename;
des_block *deskey;
{
cryptkeyarg arg;
cryptkeyres res;
arg.remotename = (char *) remotename;
arg.deskey = *deskey;
if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
(xdrproc_t)xdr_cryptkeyres, &res)) {
return (-1);
}
if (res.status != KEY_SUCCESS) {
debug("decrypt status is nonzero");
return (-1);
}
*deskey = res.cryptkeyres_u.deskey;
return (0);
}
int
key_gendes(key)
des_block *key;
{
if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_des_block, key)) {
return (-1);
}
return (0);
}
int
key_setnet(arg)
struct key_netstarg *arg;
{
keystatus status;
if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg,
(xdrproc_t)xdr_keystatus, &status)){
return (-1);
}
if (status != KEY_SUCCESS) {
debug("key_setnet status is nonzero");
return (-1);
}
return (1);
}
int
key_get_conv(pkey, deskey)
char *pkey;
des_block *deskey;
{
cryptkeyres res;
if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey,
(xdrproc_t)xdr_cryptkeyres, &res)) {
return (-1);
}
if (res.status != KEY_SUCCESS) {
debug("get_conv status is nonzero");
return (-1);
}
*deskey = res.cryptkeyres_u.deskey;
return (0);
}
struct key_call_private {
CLIENT *client; /* Client handle */
pid_t pid; /* process-id at moment of creation */
uid_t uid; /* user-id at last authorization */
};
static struct key_call_private *key_call_private_main = NULL;
static void
key_call_destroy(void *vp)
{
struct key_call_private *kcp = (struct key_call_private *)vp;
if (kcp) {
if (kcp->client)
clnt_destroy(kcp->client);
free(kcp);
}
}
/*
* Keep the handle cached. This call may be made quite often.
*/
static CLIENT *
getkeyserv_handle(vers)
int vers;
{
void *localhandle;
struct netconfig *nconf;
struct netconfig *tpconf;
struct key_call_private *kcp = key_call_private_main;
struct timeval wait_time;
struct utsname u;
int fd;
extern thread_key_t key_call_key;
extern mutex_t tsd_lock;
#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
#define TOTAL_TRIES 5 /* Number of tries */
if (key_call_key == -1) {
mutex_lock(&tsd_lock);
if (key_call_key == -1)
thr_keycreate(&key_call_key, key_call_destroy);
mutex_unlock(&tsd_lock);
}
kcp = (struct key_call_private *)thr_getspecific(key_call_key);
if (kcp == (struct key_call_private *)NULL) {
kcp = (struct key_call_private *)malloc(sizeof (*kcp));
if (kcp == (struct key_call_private *)NULL) {
return ((CLIENT *) NULL);
}
thr_setspecific(key_call_key, (void *) kcp);
kcp->client = NULL;
}
/* if pid has changed, destroy client and rebuild */
if (kcp->client != NULL && kcp->pid != getpid()) {
clnt_destroy(kcp->client);
kcp->client = NULL;
}
if (kcp->client != NULL) {
/* if uid has changed, build client handle again */
if (kcp->uid != geteuid()) {
kcp->uid = geteuid();
auth_destroy(kcp->client->cl_auth);
kcp->client->cl_auth =
authsys_create("", kcp->uid, 0, 0, NULL);
if (kcp->client->cl_auth == NULL) {
clnt_destroy(kcp->client);
kcp->client = NULL;
return ((CLIENT *) NULL);
}
}
/* Change the version number to the new one */
clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
return (kcp->client);
}
if (!(localhandle = setnetconfig())) {
return ((CLIENT *) NULL);
}
tpconf = NULL;
#if defined(__FreeBSD__)
if (uname(&u) == -1)
#else
#if defined(i386)
if (uname(&u) == -1)
#elif defined(sparc)
if (uname(&u) == -1)
#else
#error Unknown architecture!
#endif
#endif
{
endnetconfig(localhandle);
return ((CLIENT *) NULL);
}
while ((nconf = getnetconfig(localhandle)) != NULL) {
if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
/*
* We use COTS_ORD here so that the caller can
* find out immediately if the server is dead.
*/
if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
kcp->client = clnt_tp_create(u.nodename,
KEY_PROG, vers, nconf);
if (kcp->client)
break;
} else {
tpconf = nconf;
}
}
}
if ((kcp->client == (CLIENT *) NULL) && (tpconf))
/* Now, try the CLTS or COTS loopback transport */
kcp->client = clnt_tp_create(u.nodename,
KEY_PROG, vers, tpconf);
endnetconfig(localhandle);
if (kcp->client == (CLIENT *) NULL) {
return ((CLIENT *) NULL);
}
kcp->uid = geteuid();
kcp->pid = getpid();
kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
if (kcp->client->cl_auth == NULL) {
clnt_destroy(kcp->client);
kcp->client = NULL;
return ((CLIENT *) NULL);
}
wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
wait_time.tv_usec = 0;
(void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
(char *)&wait_time);
if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
return (kcp->client);
}
/* returns 0 on failure, 1 on success */
static int
key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
u_long proc;
xdrproc_t xdr_arg;
void *arg;
xdrproc_t xdr_rslt;
void *rslt;
{
CLIENT *clnt;
struct timeval wait_time;
if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
cryptkeyres *res;
res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg);
*(cryptkeyres*)rslt = *res;
return (1);
} else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
cryptkeyres *res;
res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg);
*(cryptkeyres*)rslt = *res;
return (1);
} else if (proc == KEY_GEN && __key_gendes_LOCAL) {
des_block *res;
res = (*__key_gendes_LOCAL)(geteuid(), 0);
*(des_block*)rslt = *res;
return (1);
}
if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
(proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
(proc == KEY_GET_CONV))
clnt = getkeyserv_handle(2); /* talk to version 2 */
else
clnt = getkeyserv_handle(1); /* talk to version 1 */
if (clnt == NULL) {
return (0);
}
wait_time.tv_sec = TOTAL_TIMEOUT;
wait_time.tv_usec = 0;
if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
wait_time) == RPC_SUCCESS) {
return (1);
} else {
return (0);
}
}
#endif

173
libtirpc/src/key_prot_xdr.c Normal file
View file

@ -0,0 +1,173 @@
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _WIN32
#include <rpc/key_prot.h>
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
//#include <sys/cdefs.h>
/*
* Compiled from key_prot.x using rpcgen.
* DO NOT EDIT THIS FILE!
* This is NOT source code!
*/
bool_t
xdr_keystatus(register XDR *xdrs, keystatus *objp)
{
if (!xdr_enum(xdrs, (enum_t *)objp))
return (FALSE);
return (TRUE);
}
bool_t
xdr_keybuf(register XDR *xdrs, keybuf objp)
{
if (!xdr_opaque(xdrs, objp, HEXKEYBYTES))
return (FALSE);
return (TRUE);
}
bool_t
xdr_netnamestr(register XDR *xdrs, netnamestr *objp)
{
if (!xdr_string(xdrs, objp, MAXNETNAMELEN))
return (FALSE);
return (TRUE);
}
bool_t
xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
{
if (!xdr_netnamestr(xdrs, &objp->remotename))
return (FALSE);
if (!xdr_des_block(xdrs, &objp->deskey))
return (FALSE);
return (TRUE);
}
bool_t
xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp)
{
if (!xdr_netnamestr(xdrs, &objp->remotename))
return (FALSE);
if (!xdr_netobj(xdrs, &objp->remotekey))
return (FALSE);
if (!xdr_des_block(xdrs, &objp->deskey))
return (FALSE);
return (TRUE);
}
bool_t
xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
{
if (!xdr_keystatus(xdrs, &objp->status))
return (FALSE);
switch (objp->status) {
case KEY_SUCCESS:
if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey))
return (FALSE);
break;
default:
break;
}
return (TRUE);
}
bool_t
xdr_unixcred(register XDR *xdrs, unixcred *objp)
{
if (!xdr_u_int(xdrs, &objp->uid))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->gid))
return (FALSE);
if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS,
sizeof (u_int), (xdrproc_t) xdr_u_int))
return (FALSE);
return (TRUE);
}
bool_t
xdr_getcredres(register XDR *xdrs, getcredres *objp)
{
if (!xdr_keystatus(xdrs, &objp->status))
return (FALSE);
switch (objp->status) {
case KEY_SUCCESS:
if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred))
return (FALSE);
break;
default:
break;
}
return (TRUE);
}
bool_t
xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
{
if (!xdr_keybuf(xdrs, objp->st_priv_key))
return (FALSE);
if (!xdr_keybuf(xdrs, objp->st_pub_key))
return (FALSE);
if (!xdr_netnamestr(xdrs, &objp->st_netname))
return (FALSE);
return (TRUE);
}
bool_t
xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
{
if (!xdr_keystatus(xdrs, &objp->status))
return (FALSE);
switch (objp->status) {
case KEY_SUCCESS:
if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet))
return (FALSE);
break;
default:
break;
}
return (TRUE);
}
#endif

View file

@ -0,0 +1,4 @@
SECTIONS .TIRPCP READ WRITE SHARED
EXPORTS

8
libtirpc/src/makefile Normal file
View file

@ -0,0 +1,8 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

180
libtirpc/src/mt_misc.c Normal file
View file

@ -0,0 +1,180 @@
#include <wintirpc.h>
//#include <sys/cdefs.h>
//#include <pthread.h>
#include <reentrant.h>
#include <rpc/rpc.h>
//#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
/*
* XXX
* For Windows, these must initialized in the DLLMain() function.
* Cannot do static initialization!!
* XXX
*/
/* protects the services list (svc.c) */
rwlock_t svc_lock;
/* protects svc_fdset and the xports[] array */
rwlock_t svc_fd_lock;
/* protects the RPCBIND address cache */
rwlock_t rpcbaddr_cache_lock;
/* protects authdes cache (svcauth_des.c) */
mutex_t authdes_lock;
/* serializes authdes ops initializations */
mutex_t authdes_ops_lock;
/* protects des stats list */
mutex_t svcauthdesstats_lock;
#ifdef KERBEROS
/* auth_kerb.c serialization */
mutex_t authkerb_lock = PTHREAD_MUTEX_INITIALIZER;
/* protects kerb stats list */
mutex_t svcauthkerbstats_lock = PTHREAD_MUTEX_INITIALIZER;
#endif /* KERBEROS */
/* auth_none.c serialization */
mutex_t authnone_lock;
/* protects the Auths list (svc_auth.c) */
mutex_t authsvc_lock;
/* protects client-side fd lock array */
mutex_t clnt_fd_lock;
/* clnt_raw.c serialization */
mutex_t clntraw_lock;
/* domainname and domain_fd (getdname.c) and default_domain (rpcdname.c) */
mutex_t dname_lock;
/* dupreq variables (svc_dg.c) */
mutex_t dupreq_lock;
/* protects first_time and hostname (key_call.c) */
mutex_t keyserv_lock;
/* serializes rpc_trace() (rpc_trace.c) */
mutex_t libnsl_trace_lock;
/* loopnconf (rpcb_clnt.c) */
mutex_t loopnconf_lock;
/* serializes ops initializations */
mutex_t ops_lock;
/* protects ``port'' static in bindresvport() */
mutex_t portnum_lock;
/* protects proglst list (svc_simple.c) */
mutex_t proglst_lock;
/* serializes clnt_com_create() (rpc_soc.c) */
mutex_t rpcsoc_lock;
/* svc_raw.c serialization */
mutex_t svcraw_lock;
/* protects TSD key creation */
mutex_t tsd_lock;
/* Library global tsd keys */
thread_key_t clnt_broadcast_key;
thread_key_t rpc_call_key = -1;
thread_key_t tcp_key = -1;
thread_key_t udp_key = -1;
thread_key_t nc_key = -1;
thread_key_t rce_key = -1;
/* xprtlist (svc_generic.c) */
mutex_t xprtlist_lock;
/* serializes calls to public key routines */
mutex_t serialize_pkey;
/* netconfig serialization */
mutex_t nc_lock;
#ifdef _WIN32
/*
* Initialize all the mutexes (CriticalSections)
*/
void multithread_init(void)
{
InitializeCriticalSection(&authdes_lock);
InitializeCriticalSection(&authdes_ops_lock);
InitializeCriticalSection(&svcauthdesstats_lock);
InitializeCriticalSection(&authnone_lock);
InitializeCriticalSection(&authsvc_lock);
InitializeCriticalSection(&clnt_fd_lock);
InitializeCriticalSection(&clntraw_lock);
InitializeCriticalSection(&dname_lock);
InitializeCriticalSection(&dupreq_lock);
InitializeCriticalSection(&keyserv_lock);
InitializeCriticalSection(&libnsl_trace_lock);
InitializeCriticalSection(&loopnconf_lock);
InitializeCriticalSection(&ops_lock);
InitializeCriticalSection(&portnum_lock);
InitializeCriticalSection(&proglst_lock);
InitializeCriticalSection(&rpcsoc_lock);
InitializeCriticalSection(&svcraw_lock);
InitializeCriticalSection(&tsd_lock);
InitializeCriticalSection(&xprtlist_lock);
InitializeCriticalSection(&serialize_pkey);
InitializeCriticalSection(&nc_lock);
}
#endif
#undef rpc_createerr
struct rpc_createerr rpc_createerr;
struct rpc_createerr *
__rpc_createerr()
{
struct rpc_createerr *rce_addr;
mutex_lock(&tsd_lock);
if (rce_key == -1)
rce_key = TlsAlloc(); //thr_keycreate(&rce_key, free);
mutex_unlock(&tsd_lock);
rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key);
if (!rce_addr) {
rce_addr = (struct rpc_createerr *)
malloc(sizeof (struct rpc_createerr));
if (!rce_addr ||
thr_setspecific(rce_key, (void *) rce_addr) == 0) {
if (rce_addr)
free(rce_addr);
return (&rpc_createerr);
}
memset(rce_addr, 0, sizeof (struct rpc_createerr));
}
return (rce_addr);
}
void tsd_key_delete(void)
{
if (clnt_broadcast_key != -1)
thr_keydelete(clnt_broadcast_key);
if (rpc_call_key != -1)
thr_keydelete(rpc_call_key);
if (tcp_key != -1)
thr_keydelete(tcp_key);
if (udp_key != -1)
thr_keydelete(udp_key);
if (nc_key != -1)
thr_keydelete(nc_key);
if (rce_key != -1)
thr_keydelete(rce_key);
return;
}

150
libtirpc/src/netname.c Normal file
View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* netname utility routines
* convert from unix names to network names and vice-versa
* This module is operating system dependent!
* What we define here will work with any unix system that has adopted
* the sun NIS domain architecture.
*/
#include <wintirpc.h>
//#include <sys/param.h>
#include <rpc/rpc.h>
#include "rpc_com.h"
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#ifndef NGROUPS
#define NGROUPS 16
#endif
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type) -1) < 0)
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
** add one for integer division truncation;
** add one more for a minus sign if the type is signed.
*/
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
static char *OPSYS = "unix";
/*
* Figure out my fully qualified network name
*/
int
getnetname(name)
char name[MAXNETNAMELEN+1];
{
#ifdef _WIN32
/* I don't understand what these underlying routines are accomplishing??? */
return 1;
#else
uid_t uid;
uid = geteuid();
if (uid == 0) {
return (host2netname(name, (char *) NULL, (char *) NULL));
} else {
return (user2netname(name, uid, (char *) NULL));
}
#endif
}
#ifndef _WIN32
/*
* Convert unix cred to network-name
*/
int
user2netname(netname, uid, domain)
char netname[MAXNETNAMELEN + 1];
const uid_t uid;
const char *domain;
{
char *dfltdom;
if (domain == NULL) {
if (__rpc_get_default_domain(&dfltdom) != 0) {
return (0);
}
domain = dfltdom;
}
if (strlen(domain) + 1 + INT_STRLEN_MAXIMUM(u_long) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
return (0);
}
(void) sprintf(netname, "%s.%ld@%s", OPSYS, (u_long)uid, domain);
return (1);
}
/*
* Convert host to network-name
*/
int
host2netname(netname, host, domain)
char netname[MAXNETNAMELEN + 1];
const char *host;
const char *domain;
{
char *dfltdom;
char hostname[MAXHOSTNAMELEN+1];
if (domain == NULL) {
if (__rpc_get_default_domain(&dfltdom) != 0) {
return (0);
}
domain = dfltdom;
}
if (host == NULL) {
(void) gethostname(hostname, sizeof(hostname));
host = hostname;
}
if (strlen(domain) + 1 + strlen(host) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
return (0);
}
(void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain);
return (1);
}
#endif

327
libtirpc/src/netnamer.c Normal file
View file

@ -0,0 +1,327 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* netname utility routines convert from unix names to network names and
* vice-versa This module is operating system dependent! What we define here
* will work with any unix system that has adopted the sun NIS domain
* architecture.
*/
#include <wintirpc.h>
#ifndef _WIN32
#include <sys/param.h>
#include <rpc/rpc.h>
#include "rpc_com.h"
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <grp.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
static char *OPSYS = "unix";
static char *NETID = "netid.byname";
static char *NETIDFILE = "/etc/netid";
static int getnetid( char *, char * );
static int _getgroups( char *, gid_t * );
#ifndef NGROUPS
#define NGROUPS 16
#endif
/*
* Convert network-name into unix credential
*/
int
netname2user(netname, uidp, gidp, gidlenp, gidlist)
char netname[MAXNETNAMELEN + 1];
uid_t *uidp;
gid_t *gidp;
int *gidlenp;
gid_t *gidlist;
{
char *p;
int gidlen;
uid_t uid;
long luid;
struct passwd *pwd;
char val[1024];
char *val1, *val2;
char *domain;
int vallen;
int err;
if (getnetid(netname, val)) {
char *res = val;
p = strsep(&res, ":");
if (p == NULL)
return (0);
*uidp = (uid_t) atol(p);
p = strsep(&res, "\n,");
if (p == NULL) {
return (0);
}
*gidp = (gid_t) atol(p);
gidlen = 0;
for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
p = strsep(&res, "\n,");
if (p == NULL)
break;
gidlist[gidlen] = (gid_t) atol(p);
}
*gidlenp = gidlen;
return (1);
}
val1 = strchr(netname, '.');
if (val1 == NULL)
return (0);
if (strncmp(netname, OPSYS, (val1-netname)))
return (0);
val1++;
val2 = strchr(val1, '@');
if (val2 == NULL)
return (0);
vallen = val2 - val1;
if (vallen > (1024 - 1))
vallen = 1024 - 1;
(void) strncpy(val, val1, 1024);
val[vallen] = 0;
err = __rpc_get_default_domain(&domain); /* change to rpc */
if (err)
return (0);
if (strcmp(val2 + 1, domain))
return (0); /* wrong domain */
if (sscanf(val, "%ld", &luid) != 1)
return (0);
uid = luid;
/* use initgroups method */
pwd = getpwuid(uid);
if (pwd == NULL)
return (0);
*uidp = pwd->pw_uid;
*gidp = pwd->pw_gid;
*gidlenp = _getgroups(pwd->pw_name, gidlist);
return (1);
}
/*
* initgroups
*/
static int
_getgroups(uname, groups)
char *uname;
gid_t groups[NGROUPS];
{
gid_t ngroups = 0;
struct group *grp;
int i;
int j;
int filter;
setgrent();
while ((grp = getgrent())) {
for (i = 0; grp->gr_mem[i]; i++)
if (!strcmp(grp->gr_mem[i], uname)) {
if (ngroups == NGROUPS) {
#ifdef DEBUG
fprintf(stderr,
"initgroups: %s is in too many groups\n", uname);
#endif
goto toomany;
}
/* filter out duplicate group entries */
filter = 0;
for (j = 0; j < ngroups; j++)
if (groups[j] == grp->gr_gid) {
filter++;
break;
}
if (!filter)
groups[ngroups++] = grp->gr_gid;
}
}
toomany:
endgrent();
return (ngroups);
}
/*
* Convert network-name to hostname
*/
int
netname2host(netname, hostname, hostlen)
char netname[MAXNETNAMELEN + 1];
char *hostname;
int hostlen;
{
int err;
char valbuf[1024];
char *val;
char *val2;
int vallen;
char *domain;
if (getnetid(netname, valbuf)) {
val = valbuf;
if ((*val == '0') && (val[1] == ':')) {
(void) strncpy(hostname, val + 2, hostlen);
return (1);
}
}
val = strchr(netname, '.');
if (val == NULL)
return (0);
if (strncmp(netname, OPSYS, (val - netname)))
return (0);
val++;
val2 = strchr(val, '@');
if (val2 == NULL)
return (0);
vallen = val2 - val;
if (vallen > (hostlen - 1))
vallen = hostlen - 1;
(void) strncpy(hostname, val, vallen);
hostname[vallen] = 0;
err = __rpc_get_default_domain(&domain); /* change to rpc */
if (err)
return (0);
if (strcmp(val2 + 1, domain))
return (0); /* wrong domain */
else
return (1);
}
/*
* reads the file /etc/netid looking for a + to optionally go to the
* network information service.
*/
int
getnetid(key, ret)
char *key, *ret;
{
char buf[1024]; /* big enough */
char *res;
char *mkey;
char *mval;
FILE *fd;
#ifdef YP
char *domain;
int err;
char *lookup;
int len;
#endif
fd = fopen(NETIDFILE, "r");
if (fd == NULL) {
#ifdef YP
res = "+";
goto getnetidyp;
#else
return (0);
#endif
}
for (;;) {
if (fd == NULL)
return (0); /* getnetidyp brings us here */
res = fgets(buf, sizeof(buf), fd);
if (res == NULL) {
fclose(fd);
return (0);
}
if (res[0] == '#')
continue;
else if (res[0] == '+') {
#ifdef YP
getnetidyp:
err = yp_get_default_domain(&domain);
if (err) {
continue;
}
lookup = NULL;
err = yp_match(domain, NETID, key,
strlen(key), &lookup, &len);
if (err) {
#ifdef DEBUG
fprintf(stderr, "match failed error %d\n", err);
#endif
continue;
}
lookup[len] = 0;
strcpy(ret, lookup);
free(lookup);
if (fd != NULL)
fclose(fd);
return (2);
#else /* YP */
#ifdef DEBUG
fprintf(stderr,
"Bad record in %s '+' -- NIS not supported in this library copy\n",
NETIDFILE);
#endif
continue;
#endif /* YP */
} else {
mkey = strsep(&res, "\t ");
if (mkey == NULL) {
fprintf(stderr,
"Bad record in %s -- %s", NETIDFILE, buf);
continue;
}
do {
mval = strsep(&res, " \t#\n");
} while (mval != NULL && !*mval);
if (mval == NULL) {
fprintf(stderr,
"Bad record in %s val problem - %s", NETIDFILE, buf);
continue;
}
if (strcmp(mkey, key) == 0) {
strcpy(ret, mval);
fclose(fd);
return (1);
}
}
}
}
#endif /* !_WIN32 */

111
libtirpc/src/pmap_clnt.c Normal file
View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* pmap_clnt.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <rpc/nettype.h>
//#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include "rpc_com.h"
bool_t
pmap_set(u_long program, u_long version, int protocol, int port)
{
bool_t rslt;
struct netbuf *na;
struct netconfig *nconf;
char buf[32];
if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
return (FALSE);
}
nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
if (nconf == NULL) {
return (FALSE);
}
snprintf(buf, sizeof buf, "0.0.0.0.%d.%d",
(((u_int32_t)port) >> 8) & 0xff, port & 0xff);
na = uaddr2taddr(nconf, buf);
if (na == NULL) {
freenetconfigent(nconf);
return (FALSE);
}
rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na);
free(na);
freenetconfigent(nconf);
return (rslt);
}
/*
* Remove the mapping between program, version and port.
* Calls the pmap service remotely to do the un-mapping.
*/
bool_t
pmap_unset(u_long program, u_long version)
{
struct netconfig *nconf;
bool_t udp_rslt = FALSE;
bool_t tcp_rslt = FALSE;
nconf = __rpc_getconfip("udp");
if (nconf != NULL) {
udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
nconf);
freenetconfigent(nconf);
}
nconf = __rpc_getconfip("tcp");
if (nconf != NULL) {
tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
nconf);
freenetconfigent(nconf);
}
/*
* XXX: The call may still succeed even if only one of the
* calls succeeded. This was the best that could be
* done for backward compatibility.
*/
return (tcp_rslt || udp_rslt);
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* pmap_getmap.c
* Client interface to pmap rpc service.
* contains pmap_getmaps, which is only tcp service involved
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <sys/ioctl.h>
//#include <arpa/inet.h>
//#include <net/if.h>
#include <assert.h>
#include <errno.h>
//#include <netdb.h>
#include <stdio.h>
//#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
//#include <clnt_soc.h>
#define NAMELEN 255
#define MAX_BROADCAST_SIZE 1400
/*
* Get a copy of the current port maps.
* Calls the pmap service remotely to do get the maps.
*/
struct pmaplist *
pmap_getmaps(address)
struct sockaddr_in *address;
{
struct pmaplist *head = NULL;
SOCKET sock = INVALID_SOCKET;
struct timeval minutetimeout;
CLIENT *client;
assert(address != NULL);
minutetimeout.tv_sec = 60;
minutetimeout.tv_usec = 0;
address->sin_port = htons(PMAPPORT);
client = clnttcp_create(address, PMAPPROG,
PMAPVERS, &sock, 50, 500);
if (client != NULL) {
if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP,
(xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_pmaplist, &head, minutetimeout) !=
RPC_SUCCESS) {
clnt_perror(client, "pmap_getmaps rpc problem");
}
CLNT_DESTROY(client);
}
address->sin_port = 0;
return (head);
}

109
libtirpc/src/pmap_getport.c Normal file
View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <arpa/inet.h>
//#include <net/if.h>
#include <assert.h>
//#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
static const struct timeval timeout = { 5, 0 };
static const struct timeval tottimeout = { 60, 0 };
#ifdef _WIN32
/*
* pmap_getport.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
u_short
pmap_getport(address, program, version, protocol)
struct sockaddr_in *address;
u_long program;
u_long version;
u_int protocol;
{
return (u_short)2049;
}
#else
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
u_short
pmap_getport(address, program, version, protocol)
struct sockaddr_in *address;
u_long program;
u_long version;
u_int protocol;
{
u_short port = 0;
int sock = -1;
CLIENT *client;
struct pmap parms;
assert(address != NULL);
address->sin_port = htons(PMAPPORT);
client = clntudp_bufcreate(address, PMAPPROG,
PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != NULL) {
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = 0; /* not needed or used */
if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
(xdrproc_t)xdr_pmap,
&parms, (xdrproc_t)xdr_u_short, &port, tottimeout) !=
RPC_SUCCESS){
rpc_createerr.cf_stat = RPC_PMAPFAILURE;
clnt_geterr(client, &rpc_createerr.cf_error);
} else if (port == 0) {
rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
}
CLNT_DESTROY(client);
}
address->sin_port = 0;
return (port);
}
#endif /* ! _WIN32 */

58
libtirpc/src/pmap_prot.c Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* pmap_prot.c
* Protocol for the local binder service, or pmap.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <assert.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
bool_t
xdr_pmap(xdrs, regs)
XDR *xdrs;
struct pmap *regs;
{
assert(xdrs != NULL);
assert(regs != NULL);
if (xdr_u_long(xdrs, &regs->pm_prog) &&
xdr_u_long(xdrs, &regs->pm_vers) &&
xdr_u_long(xdrs, &regs->pm_prot))
return (xdr_u_long(xdrs, &regs->pm_port));
return (FALSE);
}

132
libtirpc/src/pmap_prot2.c Normal file
View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* pmap_prot2.c
* Protocol for the local binder service, or pmap.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <assert.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
/*
* What is going on with linked lists? (!)
* First recall the link list declaration from pmap_prot.h:
*
* struct pmaplist {
* struct pmap pml_map;
* struct pmaplist *pml_map;
* };
*
* Compare that declaration with a corresponding xdr declaration that
* is (a) pointer-less, and (b) recursive:
*
* typedef union switch (bool_t) {
*
* case TRUE: struct {
* struct pmap;
* pmaplist_t foo;
* };
*
* case FALSE: struct {};
* } pmaplist_t;
*
* Notice that the xdr declaration has no nxt pointer while
* the C declaration has no bool_t variable. The bool_t can be
* interpreted as ``more data follows me''; if FALSE then nothing
* follows this bool_t; if TRUE then the bool_t is followed by
* an actual struct pmap, and then (recursively) by the
* xdr union, pamplist_t.
*
* This could be implemented via the xdr_union primitive, though this
* would cause a one recursive call per element in the list. Rather than do
* that we can ``unwind'' the recursion
* into a while loop and do the union arms in-place.
*
* The head of the list is what the C programmer wishes to past around
* the net, yet is the data that the pointer points to which is interesting;
* this sounds like a job for xdr_reference!
*/
bool_t
xdr_pmaplist(xdrs, rp)
XDR *xdrs;
struct pmaplist **rp;
{
/*
* more_elements is pre-computed in case the direction is
* XDR_ENCODE or XDR_FREE. more_elements is overwritten by
* xdr_bool when the direction is XDR_DECODE.
*/
bool_t more_elements;
int freeing;
struct pmaplist **next = NULL; /* pacify gcc */
assert(xdrs != NULL);
assert(rp != NULL);
freeing = (xdrs->x_op == XDR_FREE);
for (;;) {
more_elements = (bool_t)(*rp != NULL);
if (! xdr_bool(xdrs, &more_elements))
return (FALSE);
if (! more_elements)
return (TRUE); /* we are done */
/*
* the unfortunate side effect of non-recursion is that in
* the case of freeing we must remember the next object
* before we free the current object ...
*/
if (freeing)
next = &((*rp)->pml_next);
if (! xdr_reference(xdrs, (caddr_t *)rp,
(u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))
return (FALSE);
rp = (freeing) ? next : &((*rp)->pml_next);
}
}
/*
* xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in
* functionality to xdr_pmaplist().
*/
bool_t
xdr_pmaplist_ptr(xdrs, rp)
XDR *xdrs;
struct pmaplist *rp;
{
return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);
}

169
libtirpc/src/pmap_rmt.c Normal file
View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* pmap_rmt.c
* Client interface to pmap rpc service.
* remote call and broadcast service
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <sys/types.h>
//#include <sys/ioctl.h>
//#include <sys/poll.h>
//#include <sys/socket.h>
//#include <net/if.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>
#include <assert.h>
//#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
//#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_rmt.h>
// For the clnttcp_create function
//#include <clnt_soc.h>
static const struct timeval timeout = { 3, 0 };
/*
* pmapper remote-call-service interface.
* This routine is used to call the pmapper remote call service
* which will look up a service program in the port maps, and then
* remotely call that routine with the given parameters. This allows
* programs to do a lookup and call in one step.
*/
enum clnt_stat
pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout,
port_ptr)
struct sockaddr_in *addr;
u_long prog, vers, proc;
xdrproc_t xdrargs, xdrres;
caddr_t argsp, resp;
struct timeval tout;
u_long *port_ptr;
{
int sock = -1;
CLIENT *client;
struct rmtcallargs a;
struct rmtcallres r;
enum clnt_stat stat;
assert(addr != NULL);
assert(port_ptr != NULL);
addr->sin_port = htons(PMAPPORT);
client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
if (client != NULL) {
a.prog = prog;
a.vers = vers;
a.proc = proc;
a.args_ptr = argsp;
a.xdr_args = xdrargs;
r.port_ptr = port_ptr;
r.results_ptr = resp;
r.xdr_results = xdrres;
stat = CLNT_CALL(client, (rpcproc_t)PMAPPROC_CALLIT,
(xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres,
&r, tout);
CLNT_DESTROY(client);
} else {
stat = RPC_FAILED;
}
addr->sin_port = 0;
return (stat);
}
/*
* XDR remote call arguments
* written for XDR_ENCODE direction only
*/
bool_t
xdr_rmtcall_args(xdrs, cap)
XDR *xdrs;
struct rmtcallargs *cap;
{
u_int lenposition, argposition, position;
assert(xdrs != NULL);
assert(cap != NULL);
if (xdr_u_long(xdrs, &(cap->prog)) &&
xdr_u_long(xdrs, &(cap->vers)) &&
xdr_u_long(xdrs, &(cap->proc))) {
lenposition = XDR_GETPOS(xdrs);
if (! xdr_u_long(xdrs, &(cap->arglen)))
return (FALSE);
argposition = XDR_GETPOS(xdrs);
if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
return (FALSE);
position = XDR_GETPOS(xdrs);
cap->arglen = (u_long)position - (u_long)argposition;
XDR_SETPOS(xdrs, lenposition);
if (! xdr_u_long(xdrs, &(cap->arglen)))
return (FALSE);
XDR_SETPOS(xdrs, position);
return (TRUE);
}
return (FALSE);
}
/*
* XDR remote call results
* written for XDR_DECODE direction only
*/
bool_t
xdr_rmtcallres(xdrs, crp)
XDR *xdrs;
struct rmtcallres *crp;
{
caddr_t port_ptr;
assert(xdrs != NULL);
assert(crp != NULL);
port_ptr = (caddr_t)(void *)crp->port_ptr;
if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
(xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
crp->port_ptr = (u_long *)(void *)port_ptr;
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
}
return (FALSE);
}

197
libtirpc/src/rpc_callmsg.c Normal file
View file

@ -0,0 +1,197 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* rpc_callmsg.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
#include <wintirpc.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
//#include <sys/select.h>
/*
* XDR a call message
*/
bool_t
xdr_callmsg(xdrs, cmsg)
XDR *xdrs;
struct rpc_msg *cmsg;
{
int32_t *buf;
struct opaque_auth *oa;
assert(xdrs != NULL);
assert(cmsg != NULL);
if (xdrs->x_op == XDR_ENCODE) {
if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
return (FALSE);
}
if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
return (FALSE);
}
buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
+ 2 * BYTES_PER_XDR_UNIT
+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
if (buf != NULL) {
IXDR_PUT_INT32(buf, cmsg->rm_xid);
IXDR_PUT_ENUM(buf, cmsg->rm_direction);
if (cmsg->rm_direction != CALL) {
return (FALSE);
}
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
return (FALSE);
}
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog);
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers);
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc);
oa = &cmsg->rm_call.cb_cred;
IXDR_PUT_ENUM(buf, oa->oa_flavor);
IXDR_PUT_INT32(buf, oa->oa_length);
if (oa->oa_length) {
memmove(buf, oa->oa_base, oa->oa_length);
buf += RNDUP(oa->oa_length) / sizeof (int32_t);
}
oa = &cmsg->rm_call.cb_verf;
IXDR_PUT_ENUM(buf, oa->oa_flavor);
IXDR_PUT_INT32(buf, oa->oa_length);
if (oa->oa_length) {
memmove(buf, oa->oa_base, oa->oa_length);
/* no real need....
buf += RNDUP(oa->oa_length) / sizeof (int32_t);
*/
}
return (TRUE);
}
}
if (xdrs->x_op == XDR_DECODE) {
buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
if (buf != NULL) {
cmsg->rm_xid = IXDR_GET_U_INT32(buf);
cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
if (cmsg->rm_direction != CALL) {
return (FALSE);
}
cmsg->rm_call.cb_rpcvers = IXDR_GET_U_INT32(buf);
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
return (FALSE);
}
cmsg->rm_call.cb_prog = IXDR_GET_U_INT32(buf);
cmsg->rm_call.cb_vers = IXDR_GET_U_INT32(buf);
cmsg->rm_call.cb_proc = IXDR_GET_U_INT32(buf);
oa = &cmsg->rm_call.cb_cred;
oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
if (oa->oa_length) {
if (oa->oa_length > MAX_AUTH_BYTES) {
return (FALSE);
}
if (oa->oa_base == NULL) {
oa->oa_base = (caddr_t)
mem_alloc(oa->oa_length);
if (oa->oa_base == NULL)
return (FALSE);
}
buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
if (buf == NULL) {
if (xdr_opaque(xdrs, oa->oa_base,
oa->oa_length) == FALSE) {
return (FALSE);
}
} else {
memmove(oa->oa_base, buf,
oa->oa_length);
/* no real need....
buf += RNDUP(oa->oa_length) /
sizeof (int32_t);
*/
}
}
oa = &cmsg->rm_call.cb_verf;
buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
return (FALSE);
}
} else {
oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
}
if (oa->oa_length) {
if (oa->oa_length > MAX_AUTH_BYTES) {
return (FALSE);
}
if (oa->oa_base == NULL) {
oa->oa_base = (caddr_t)
mem_alloc(oa->oa_length);
if (oa->oa_base == NULL)
return (FALSE);
}
buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
if (buf == NULL) {
if (xdr_opaque(xdrs, oa->oa_base,
oa->oa_length) == FALSE) {
return (FALSE);
}
} else {
memmove(oa->oa_base, buf,
oa->oa_length);
/* no real need...
buf += RNDUP(oa->oa_length) /
sizeof (int32_t);
*/
}
}
return (TRUE);
}
}
if (
xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
(cmsg->rm_direction == CALL) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
(cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
return (FALSE);
}

100
libtirpc/src/rpc_com.h Normal file
View file

@ -0,0 +1,100 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/*
* rpc_com.h, Common definitions for both the server and client side.
* All for the topmost layer of rpc
*
* In Sun's tirpc distribution, this was installed as <rpc/rpc_com.h>,
* but as it contains only non-exported interfaces, it was moved here.
*/
#ifndef _TIRPC_RPCCOM_H
#define _TIRPC_RPCCOM_H
//#include <sys/cdefs.h>
/* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */
/*
* The max size of the transport, if the size cannot be determined
* by other means.
*/
#define RPC_MAXDATASIZE 9000
#define RPC_MAXADDRSIZE 1024
//#ifdef _WIN32
// #define __RPC_GETXID(now) ((u_int32_t)_getpid() ^ (u_int32_t)(now)->tv_sec ^ \
// (u_int32_t)(now)->tv_usec)
//#else
#define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \
(u_int32_t)(now)->tv_usec)
//#endif
__BEGIN_DECLS
extern u_int __rpc_get_a_size(int);
extern int __rpc_dtbsize(void);
extern struct netconfig * __rpcgettp(SOCKET);
extern int __rpc_get_default_domain(char **);
struct netbuf *__rpc_set_netbuf(struct netbuf *, const void *, size_t);
char *__rpc_taddr2uaddr_af(int, const struct netbuf *);
struct netbuf *__rpc_uaddr2taddr_af(int, const char *);
int __rpc_fixup_addr(struct netbuf *, const struct netbuf *);
int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **);
int __rpc_seman2socktype(int);
int __rpc_socktype2seman(int);
void *rpc_nullproc(CLIENT *);
int __rpc_sockisbound(SOCKET);
struct netbuf *__rpcb_findaddr(rpcprog_t, rpcvers_t, const struct netconfig *,
const char *, CLIENT **);
struct netbuf *__rpcb_findaddr_timed(rpcprog_t, rpcvers_t,
const struct netconfig *, const char *host, CLIENT **clpp,
struct timeval *tp);
bool_t __rpc_control(int,void *);
char *_get_next_token(char *, int);
bool_t __svc_clean_idle(fd_set *, int, bool_t);
bool_t __xdrrec_setnonblock(XDR *, int);
bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
void __xprt_unregister_unlocked(SVCXPRT *);
void __xprt_set_raddr(SVCXPRT *, const struct sockaddr_storage *);
SVCXPRT **__svc_xports;
int __svc_maxrec;
__END_DECLS
#endif /* _TIRPC_RPCCOM_H */

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <wintirpc.h>
#include <rpc/rpc.h>
/*
* This file should only contain common data (global data) that is exported
* by public interfaces
*/
struct opaque_auth _null_auth;
fd_set svc_fdset;
int svc_maxfd = -1;

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <wintirpc.h>
//#include <unistd.h>
//#include <sys/select.h>
int _rpc_dtablesize(void); /* XXX */
/*
* Cache the result of getdtablesize(), so we don't have to do an
* expensive system call every time.
*/
/*
* XXX In FreeBSD 2.x, you can have the maximum number of open file
* descriptors be greater than FD_SETSIZE (which is 256 by default).
*
* Since old programs tend to use this call to determine the first arg
* for _select(), having this return > FD_SETSIZE is a Bad Idea(TM)!
*/
int
_rpc_dtablesize(void)
{
#ifdef _WIN32
return FD_SETSIZE;
#else
static int size;
if (size == 0) {
size = getdtablesize();
if (size > FD_SETSIZE)
size = FD_SETSIZE;
}
return (size);
#endif
}

920
libtirpc/src/rpc_generic.c Normal file
View file

@ -0,0 +1,920 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
//#include <sys/cdefs.h>
/*
* rpc_generic.c, Miscl routines for RPC.
*
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <sys/types.h>
//#include <sys/param.h>
//#include <sys/socket.h>
//#include <sys/time.h>
//#include <sys/un.h>
//#include <sys/resource.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>
#include <rpc/rpc.h>
//#include <ctype.h>
//#include <stddef.h>
#include <stdio.h>
//#include <netdb.h>
#include <netconfig.h>
#include <stdlib.h>
#include <string.h>
//#include <syslog.h>
#include <rpc/nettype.h>
#include "rpc_com.h"
struct handle {
NCONF_HANDLE *nhandle;
int nflag; /* Whether NETPATH or NETCONFIG */
int nettype;
};
static const struct _rpcnettype {
const char *name;
const int type;
} _rpctypelist[] = {
{ "netpath", _RPC_NETPATH },
{ "visible", _RPC_VISIBLE },
{ "circuit_v", _RPC_CIRCUIT_V },
{ "datagram_v", _RPC_DATAGRAM_V },
{ "circuit_n", _RPC_CIRCUIT_N },
{ "datagram_n", _RPC_DATAGRAM_N },
{ "tcp", _RPC_TCP },
{ "udp", _RPC_UDP },
{ 0, _RPC_NONE }
};
struct netid_af {
const char *netid;
ADDRESS_FAMILY af;
int protocol;
};
static const struct netid_af na_cvt[] = {
{ "udp", AF_INET, IPPROTO_UDP },
{ "tcp", AF_INET, IPPROTO_TCP },
#ifdef INET6
{ "udp6", AF_INET6, IPPROTO_UDP },
{ "tcp6", AF_INET6, IPPROTO_TCP },
#endif
#ifdef AF_LOCAL
{ "local", AF_LOCAL, 0 }
#endif
};
#if 0
static char *strlocase(char *);
#endif
static int getnettype(const char *);
/*
* Cache the result of getrlimit(), so we don't have to do an
* expensive call every time.
*/
int
__rpc_dtbsize()
{
#ifdef _WIN32
return (WINSOCK_HANDLE_HASH_SIZE);
#else
static int tbsize;
struct rlimit rl;
if (tbsize) {
return (tbsize);
}
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
return (tbsize = (int)rl.rlim_max);
}
/*
* Something wrong. I'll try to save face by returning a
* pessimistic number.
*/
return (32);
#endif
}
/*
* Find the appropriate buffer size
*/
u_int
/*ARGSUSED*/
__rpc_get_t_size(af, proto, size)
int af, proto;
int size; /* Size requested */
{
int maxsize, defsize;
maxsize = 256 * 1024; /* XXX */
switch (proto) {
case IPPROTO_TCP:
defsize = 1024 * 1024; /* XXX */
break;
case IPPROTO_UDP:
defsize = UDPMSGSIZE;
break;
default:
defsize = RPC_MAXDATASIZE;
break;
}
if (size == 0)
return defsize;
#if 1
/* cbodley- give us the size we ask for, or we'll get fragmented! */
return (u_int)size;
#else
/* Check whether the value is within the upper max limit */
return (size > maxsize ? (u_int)maxsize : (u_int)size);
#endif
}
/*
* Find the appropriate address buffer size
*/
u_int
__rpc_get_a_size(af)
int af;
{
switch (af) {
case AF_INET:
return sizeof (struct sockaddr_in);
#ifdef INET6
case AF_INET6:
return sizeof (struct sockaddr_in6);
#endif
#ifdef AF_LOCAL
case AF_LOCAL:
return sizeof (struct sockaddr_un);
#endif
default:
break;
}
return ((u_int)RPC_MAXADDRSIZE);
}
#if 0
static char *
strlocase(p)
char *p;
{
char *t = p;
for (; *p; p++)
if (isupper(*p))
*p = tolower(*p);
return (t);
}
#endif
/*
* Returns the type of the network as defined in <rpc/nettype.h>
* If nettype is NULL, it defaults to NETPATH.
*/
static int
getnettype(nettype)
const char *nettype;
{
int i;
if ((nettype == NULL) || (nettype[0] == 0)) {
return (_RPC_NETPATH); /* Default */
}
#if 0
nettype = strlocase(nettype);
#endif
for (i = 0; _rpctypelist[i].name; i++)
if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
return (_rpctypelist[i].type);
}
return (_rpctypelist[i].type);
}
/*
* For the given nettype (tcp or udp only), return the first structure found.
* This should be freed by calling freenetconfigent()
*/
struct netconfig *
__rpc_getconfip(nettype)
const char *nettype;
{
char *netid;
char *netid_tcp = (char *) NULL;
char *netid_udp = (char *) NULL;
struct netconfig *dummy;
extern thread_key_t tcp_key, udp_key;
extern mutex_t tsd_lock;
if (tcp_key == -1) {
mutex_lock(&tsd_lock);
if (tcp_key == -1)
tcp_key = TlsAlloc(); //thr_keycreate(&tcp_key, free);
mutex_unlock(&tsd_lock);
}
netid_tcp = (char *)thr_getspecific(tcp_key);
if (udp_key == -1) {
mutex_lock(&tsd_lock);
if (udp_key == -1)
udp_key = TlsAlloc(); //thr_keycreate(&udp_key, free);
mutex_unlock(&tsd_lock);
}
netid_udp = (char *)thr_getspecific(udp_key);
if (!netid_udp && !netid_tcp) {
struct netconfig *nconf;
void *confighandle;
if (!(confighandle = setnetconfig())) {
//syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
return (NULL);
}
while ((nconf = getnetconfig(confighandle)) != NULL) {
if (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
if (strcmp(nconf->nc_proto, NC_TCP) == 0 &&
netid_tcp == NULL) {
netid_tcp = strdup(nconf->nc_netid);
thr_setspecific(tcp_key,
(void *) netid_tcp);
} else
if (strcmp(nconf->nc_proto, NC_UDP) == 0 &&
netid_udp == NULL) {
netid_udp = strdup(nconf->nc_netid);
thr_setspecific(udp_key,
(void *) netid_udp);
}
}
}
endnetconfig(confighandle);
}
if (strcmp(nettype, "udp") == 0)
netid = netid_udp;
else if (strcmp(nettype, "tcp") == 0)
netid = netid_tcp;
else {
return (NULL);
}
if ((netid == NULL) || (netid[0] == 0)) {
return (NULL);
}
dummy = getnetconfigent(netid);
return (dummy);
}
/*
* Returns the type of the nettype, which should then be used with
* __rpc_getconf().
*/
void *
__rpc_setconf(nettype)
const char *nettype;
{
struct handle *handle;
handle = (struct handle *) malloc(sizeof (struct handle));
if (handle == NULL) {
return (NULL);
}
switch (handle->nettype = getnettype(nettype)) {
case _RPC_NETPATH:
case _RPC_CIRCUIT_N:
case _RPC_DATAGRAM_N:
if (!(handle->nhandle = setnetpath())) {
free(handle);
return (NULL);
}
handle->nflag = TRUE;
break;
case _RPC_VISIBLE:
case _RPC_CIRCUIT_V:
case _RPC_DATAGRAM_V:
case _RPC_TCP:
case _RPC_UDP:
if (!(handle->nhandle = setnetconfig())) {
//syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
free(handle);
return (NULL);
}
handle->nflag = FALSE;
break;
default:
return (NULL);
}
return (handle);
}
/*
* Returns the next netconfig struct for the given "net" type.
* __rpc_setconf() should have been called previously.
*/
struct netconfig *
__rpc_getconf(vhandle)
void *vhandle;
{
struct handle *handle;
struct netconfig *nconf;
handle = (struct handle *)vhandle;
if (handle == NULL) {
return (NULL);
}
for (;;) {
if (handle->nflag)
nconf = getnetpath(handle->nhandle);
else
nconf = getnetconfig(handle->nhandle);
if (nconf == NULL)
break;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
continue;
switch (handle->nettype) {
case _RPC_VISIBLE:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
/* FALLTHROUGH */
case _RPC_NETPATH: /* Be happy */
break;
case _RPC_CIRCUIT_V:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
/* FALLTHROUGH */
case _RPC_CIRCUIT_N:
if ((nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
continue;
break;
case _RPC_DATAGRAM_V:
if (!(nconf->nc_flag & NC_VISIBLE))
continue;
/* FALLTHROUGH */
case _RPC_DATAGRAM_N:
if (nconf->nc_semantics != NC_TPI_CLTS)
continue;
break;
case _RPC_TCP:
if (((nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
(strcmp(nconf->nc_protofmly, NC_INET)
#ifdef INET6
&& strcmp(nconf->nc_protofmly, NC_INET6))
#else
)
#endif
||
strcmp(nconf->nc_proto, NC_TCP))
continue;
break;
case _RPC_UDP:
if ((nconf->nc_semantics != NC_TPI_CLTS) ||
(strcmp(nconf->nc_protofmly, NC_INET)
#ifdef INET6
&& strcmp(nconf->nc_protofmly, NC_INET6))
#else
)
#endif
||
strcmp(nconf->nc_proto, NC_UDP))
continue;
break;
}
break;
}
return (nconf);
}
void
__rpc_endconf(vhandle)
void * vhandle;
{
struct handle *handle;
handle = (struct handle *) vhandle;
if (handle == NULL) {
return;
}
if (handle->nflag) {
endnetpath(handle->nhandle);
} else {
endnetconfig(handle->nhandle);
}
free(handle);
}
/*
* Used to ping the NULL procedure for clnt handle.
* Returns NULL if fails, else a non-NULL pointer.
*/
void *
rpc_nullproc(clnt)
CLIENT *clnt;
{
struct timeval TIMEOUT = {25, 0};
if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return ((void *) clnt);
}
/*
* Try all possible transports until
* one succeeds in finding the netconf for the given fd.
*/
struct netconfig *
__rpcgettp(fd)
SOCKET fd;
{
const char *netid;
struct __rpc_sockinfo si;
if (!__rpc_fd2sockinfo(fd, &si))
return NULL;
if (!__rpc_sockinfo2netid(&si, &netid))
return NULL;
/*LINTED const castaway*/
return getnetconfigent((char *)netid);
}
int
__rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
{
socklen_t len;
int type, proto;
struct sockaddr_storage ss;
#ifdef _WIN32
WSAPROTOCOL_INFO proto_info;
int proto_info_size = sizeof(proto_info);
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&proto_info, &proto_info_size) == SOCKET_ERROR) {
int err = WSAGetLastError();
return 0;
}
len = proto_info.iMaxSockAddr;
ss.ss_family = (ADDRESS_FAMILY)proto_info.iAddressFamily;
#else
len = sizeof ss;
if (getsockname(fd, (struct sockaddr *)&ss, &len) == SOCKET_ERROR) {
return 0;
}
#endif
sip->si_alen = len;
len = sizeof type;
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&type, &len) == SOCKET_ERROR) {
int err = WSAGetLastError();
return 0;
}
/* XXX */
#ifdef AF_LOCAL
if (ss.ss_family != AF_LOCAL) {
#endif
if (type == SOCK_STREAM)
proto = IPPROTO_TCP;
else if (type == SOCK_DGRAM)
proto = IPPROTO_UDP;
else
return 0;
#ifdef AF_LOCAL
} else
proto = 0;
#endif
sip->si_af = ss.ss_family;
sip->si_proto = proto;
sip->si_socktype = type;
return 1;
}
/*
* Linear search, but the number of entries is small.
*/
int
__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
{
int i;
for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
strcmp(nconf->nc_netid, "unix") == 0 &&
strcmp(na_cvt[i].netid, "local") == 0)) {
sip->si_af = na_cvt[i].af;
sip->si_proto = na_cvt[i].protocol;
sip->si_socktype =
__rpc_seman2socktype((int)nconf->nc_semantics);
if (sip->si_socktype == -1)
return 0;
sip->si_alen = __rpc_get_a_size(sip->si_af);
return 1;
}
return 0;
}
SOCKET
__rpc_nconf2fd(const struct netconfig *nconf)
{
struct __rpc_sockinfo si;
SOCKET fd;
if (!__rpc_nconf2sockinfo(nconf, &si))
return 0;
if ((fd = socket(si.si_af, si.si_socktype, si.si_proto)) != INVALID_SOCKET &&
si.si_af == AF_INET6) {
int val = 1;
setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (const char *)&val, sizeof(val));
}
return fd;
}
int
__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
{
int i;
struct netconfig *nconf;
nconf = getnetconfigent("local");
for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) {
if (na_cvt[i].af == sip->si_af &&
na_cvt[i].protocol == sip->si_proto) {
if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) {
if (netid)
*netid = "unix";
} else {
if (netid)
*netid = na_cvt[i].netid;
}
if (nconf != NULL)
freenetconfigent(nconf);
return 1;
}
}
if (nconf != NULL)
freenetconfigent(nconf);
return 0;
}
char *
taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
{
struct __rpc_sockinfo si;
if (!__rpc_nconf2sockinfo(nconf, &si))
return NULL;
return __rpc_taddr2uaddr_af(si.si_af, nbuf);
}
struct netbuf *
uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
{
struct __rpc_sockinfo si;
if (!__rpc_nconf2sockinfo(nconf, &si))
return NULL;
return __rpc_uaddr2taddr_af(si.si_af, uaddr);
}
void freeuaddr(char *uaddr)
{
free(uaddr);
}
void freenetbuf(struct netbuf *nbuf)
{
if (nbuf) {
free(nbuf->buf);
free(nbuf);
}
}
char *
__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
{
char *ret;
struct sockaddr_in *sin;
#ifdef AF_LOCAL
struct sockaddr_un *sun;
#endif
char namebuf[INET_ADDRSTRLEN];
#ifdef INET6
struct sockaddr_in6 *sin6;
char namebuf6[INET6_ADDRSTRLEN];
#endif
u_int16_t port;
if (nbuf->len <= 0)
return NULL;
switch (af) {
case AF_INET:
sin = nbuf->buf;
if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
== NULL)
return NULL;
port = ntohs(sin->sin_port);
if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
port & 0xff) < 0)
return NULL;
break;
#ifdef INET6
case AF_INET6:
sin6 = nbuf->buf;
if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
== NULL)
return NULL;
port = ntohs(sin6->sin6_port);
if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
port & 0xff) < 0)
return NULL;
break;
#endif
#ifdef AF_LOCAL
case AF_LOCAL:
sun = nbuf->buf;
/* if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
offsetof(struct sockaddr_un, sun_path)),
sun->sun_path) < 0)*/
if (asprintf(&ret, "%.*s", (int)(sizeof(*sun) -
offsetof(struct sockaddr_un, sun_path)),
sun->sun_path) < 0)
return (NULL);
break;
#endif
default:
return NULL;
}
return ret;
}
struct netbuf *
__rpc_uaddr2taddr_af(int af, const char *uaddr)
{
struct netbuf *ret = NULL;
char *addrstr, *p;
unsigned short port, portlo, porthi;
struct sockaddr_in *sin;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
#ifdef AF_LOCAL
struct sockaddr_un *sun;
#endif
port = 0;
sin = NULL;
addrstr = strdup(uaddr);
if (addrstr == NULL)
return NULL;
/*
* AF_LOCAL addresses are expected to be absolute
* pathnames, anything else will be AF_INET or AF_INET6.
*/
if (*addrstr != '/') {
p = strrchr(addrstr, '.');
if (p == NULL)
goto out;
portlo = (unsigned)atoi(p + 1);
*p = '\0';
p = strrchr(addrstr, '.');
if (p == NULL)
goto out;
porthi = (unsigned)atoi(p + 1);
*p = '\0';
port = (porthi << 8) | portlo;
}
ret = (struct netbuf *)malloc(sizeof *ret);
if (ret == NULL)
goto out;
switch (af) {
case AF_INET:
sin = (struct sockaddr_in *)malloc(sizeof *sin);
if (sin == NULL)
goto out;
memset(sin, 0, sizeof *sin);
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
free(sin);
free(ret);
ret = NULL;
goto out;
}
ret->maxlen = ret->len = sizeof *sin;
ret->buf = sin;
break;
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
if (sin6 == NULL)
goto out;
memset(sin6, 0, sizeof *sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
free(sin6);
free(ret);
ret = NULL;
goto out;
}
ret->maxlen = ret->len = sizeof *sin6;
ret->buf = sin6;
break;
#endif
#ifdef AF_LOCAL
case AF_LOCAL:
sun = (struct sockaddr_un *)malloc(sizeof *sun);
if (sun == NULL)
goto out;
memset(sun, 0, sizeof *sun);
sun->sun_family = AF_LOCAL;
strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
ret->len = SUN_LEN(sun);
ret->maxlen = sizeof(struct sockaddr_un);
ret->buf = sun;
break;
#endif
default:
break;
}
out:
free(addrstr);
return ret;
}
int
__rpc_seman2socktype(int semantics)
{
switch (semantics) {
case NC_TPI_CLTS:
return SOCK_DGRAM;
case NC_TPI_COTS_ORD:
return SOCK_STREAM;
case NC_TPI_RAW:
return SOCK_RAW;
default:
break;
}
return -1;
}
int
__rpc_socktype2seman(int socktype)
{
switch (socktype) {
case SOCK_DGRAM:
return NC_TPI_CLTS;
case SOCK_STREAM:
return NC_TPI_COTS_ORD;
case SOCK_RAW:
return NC_TPI_RAW;
default:
break;
}
return -1;
}
/*
* XXXX - IPv6 scope IDs can't be handled in universal addresses.
* Here, we compare the original server address to that of the RPC
* service we just received back from a call to rpcbind on the remote
* machine. If they are both "link local" or "site local", copy
* the scope id of the server address over to the service address.
*/
int
__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
{
#ifdef INET6
struct sockaddr *sa_new, *sa_svc;
struct sockaddr_in6 *sin6_new, *sin6_svc;
sa_svc = (struct sockaddr *)svc->buf;
sa_new = (struct sockaddr *)new->buf;
if (sa_new->sa_family == sa_svc->sa_family &&
sa_new->sa_family == AF_INET6) {
sin6_new = (struct sockaddr_in6 *)new->buf;
sin6_svc = (struct sockaddr_in6 *)svc->buf;
if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
(IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
}
}
#endif
return 1;
}
int
__rpc_sockisbound(SOCKET fd)
{
struct sockaddr_storage ss;
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
#ifdef AF_LOCAL
struct sockaddr_un usin;
#endif
} u_addr;
socklen_t slen;
slen = sizeof (struct sockaddr_storage);
if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR)
return 0;
switch (ss.ss_family) {
case AF_INET:
memcpy(&u_addr.sin, &ss, sizeof(u_addr.sin));
return (u_addr.sin.sin_port != 0);
#ifdef INET6
case AF_INET6:
memcpy(&u_addr.sin6, &ss, sizeof(u_addr.sin6));
return (u_addr.sin6.sin6_port != 0);
#endif
#ifdef AF_LOCAL
case AF_LOCAL:
/* XXX check this */
memcpy(&u_addr.usin, &ss, sizeof(u_addr.usin));
return (u_addr.usin.sun_path[0] != 0);
#endif
default:
break;
}
return 0;
}
/*
* Helper function to set up a netbuf
*/
struct netbuf *
__rpc_set_netbuf(struct netbuf *nb, const void *ptr, size_t len)
{
if (nb->len != len) {
if (nb->len)
mem_free(nb->buf, nb->len);
nb->buf = mem_alloc(len);
if (nb->buf == NULL)
return NULL;
nb->maxlen = nb->len = len;
}
memcpy(nb->buf, ptr, len);
return nb;
}

389
libtirpc/src/rpc_prot.c Normal file
View file

@ -0,0 +1,389 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* rpc_prot.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* This set of routines implements the rpc message definition,
* its serializer and some common rpc utility routines.
* The routines are meant for various implementations of rpc -
* they are NOT for the rpc client or rpc service implementations!
* Because authentication stuff is easy and is part of rpc, the opaque
* routines are also in this program.
*/
#include <wintirpc.h>
//#include <sys/param.h>
#include <assert.h>
#include <rpc/rpc.h>
static void accepted(enum accept_stat, struct rpc_err *);
static void rejected(enum reject_stat, struct rpc_err *);
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
extern struct opaque_auth _null_auth;
/*
* XDR an opaque authentication struct
* (see auth.h)
*/
bool_t
xdr_opaque_auth(xdrs, ap)
XDR *xdrs;
struct opaque_auth *ap;
{
assert(xdrs != NULL);
assert(ap != NULL);
if (xdr_enum(xdrs, &(ap->oa_flavor)))
return (xdr_bytes(xdrs, &ap->oa_base,
&ap->oa_length, MAX_AUTH_BYTES));
return (FALSE);
}
/*
* XDR a DES block
*/
bool_t
xdr_des_block(xdrs, blkp)
XDR *xdrs;
des_block *blkp;
{
assert(xdrs != NULL);
assert(blkp != NULL);
return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
}
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
/*
* XDR the MSG_ACCEPTED part of a reply message union
*/
bool_t
xdr_accepted_reply(xdrs, ar)
XDR *xdrs;
struct accepted_reply *ar;
{
assert(xdrs != NULL);
assert(ar != NULL);
/* personalized union, rather than calling xdr_union */
if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
return (FALSE);
if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
return (FALSE);
switch (ar->ar_stat) {
case SUCCESS:
return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
case PROG_MISMATCH:
if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
return (FALSE);
return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
case GARBAGE_ARGS:
case SYSTEM_ERR:
case PROC_UNAVAIL:
case PROG_UNAVAIL:
break;
}
return (TRUE); /* TRUE => open ended set of problems */
}
/*
* XDR the MSG_DENIED part of a reply message union
*/
bool_t
xdr_rejected_reply(xdrs, rr)
XDR *xdrs;
struct rejected_reply *rr;
{
assert(xdrs != NULL);
assert(rr != NULL);
/* personalized union, rather than calling xdr_union */
if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
return (FALSE);
switch (rr->rj_stat) {
case RPC_MISMATCH:
if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
return (FALSE);
return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
case AUTH_ERROR:
return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
}
/* NOTREACHED */
assert(0);
return (FALSE);
}
static const struct xdr_discrim reply_dscrm[3] = {
{ (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
{ (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
{ __dontcare__, NULL_xdrproc_t } };
/*
* XDR a reply message
*/
bool_t
xdr_replymsg(xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
{
assert(xdrs != NULL);
assert(rmsg != NULL);
if (
xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
(rmsg->rm_direction == REPLY) )
return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
(caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
NULL_xdrproc_t));
return (FALSE);
}
/*
* XDR a reply message in pieces, first xid and direction, then union
*/
bool_t
xdr_getxiddir(xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
{
assert(xdrs != NULL);
assert(rmsg != NULL);
return (xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)));
}
bool_t
xdr_getreplyunion(xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
{
assert(xdrs != NULL);
assert(rmsg != NULL);
return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
(caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
NULL_xdrproc_t));
}
bool_t
xdr_getcallbody(xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
{
assert(xdrs != NULL);
assert(rmsg != NULL);
if (
xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_rpcvers)) &&
xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_prog)) &&
xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_vers)) &&
xdr_u_int32_t(xdrs, &(rmsg->rm_call.cb_proc)) &&
xdr_opaque_auth(xdrs, &(rmsg->rm_call.cb_cred)) )
return (xdr_opaque_auth(xdrs, &(rmsg->rm_call.cb_verf)));
return FALSE;
}
/*
* Serializes the "static part" of a call message header.
* The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
* The rm_xid is not really static, but the user can easily munge on the fly.
*/
bool_t
xdr_callhdr(xdrs, cmsg)
XDR *xdrs;
struct rpc_msg *cmsg;
{
assert(xdrs != NULL);
assert(cmsg != NULL);
cmsg->rm_direction = CALL;
cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
if (
(xdrs->x_op == XDR_ENCODE) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
return (FALSE);
}
/* ************************** Client utility routine ************* */
static void
accepted(acpt_stat, error)
enum accept_stat acpt_stat;
struct rpc_err *error;
{
assert(error != NULL);
switch (acpt_stat) {
case PROG_UNAVAIL:
error->re_status = RPC_PROGUNAVAIL;
return;
case PROG_MISMATCH:
error->re_status = RPC_PROGVERSMISMATCH;
return;
case PROC_UNAVAIL:
error->re_status = RPC_PROCUNAVAIL;
return;
case GARBAGE_ARGS:
error->re_status = RPC_CANTDECODEARGS;
return;
case SYSTEM_ERR:
error->re_status = RPC_SYSTEMERROR;
return;
case SUCCESS:
error->re_status = RPC_SUCCESS;
return;
}
/* NOTREACHED */
/* something's wrong, but we don't know what ... */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
error->re_lb.s2 = (int32_t)acpt_stat;
}
static void
rejected(rjct_stat, error)
enum reject_stat rjct_stat;
struct rpc_err *error;
{
assert(error != NULL);
switch (rjct_stat) {
case RPC_MISMATCH:
error->re_status = RPC_VERSMISMATCH;
return;
case AUTH_ERROR:
error->re_status = RPC_AUTHERROR;
return;
}
/* something's wrong, but we don't know what ... */
/* NOTREACHED */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (int32_t)MSG_DENIED;
error->re_lb.s2 = (int32_t)rjct_stat;
}
/*
* given a reply message, fills in the error
*/
void
_seterr_reply(msg, error)
struct rpc_msg *msg;
struct rpc_err *error;
{
assert(msg != NULL);
assert(error != NULL);
/* optimized for normal, SUCCESSful case */
switch (msg->rm_reply.rp_stat) {
case MSG_ACCEPTED:
if (msg->acpted_rply.ar_stat == SUCCESS) {
error->re_status = RPC_SUCCESS;
return;
}
accepted(msg->acpted_rply.ar_stat, error);
break;
case MSG_DENIED:
rejected(msg->rjcted_rply.rj_stat, error);
break;
default:
error->re_status = RPC_FAILED;
error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
break;
}
switch (error->re_status) {
case RPC_VERSMISMATCH:
error->re_vers.low = msg->rjcted_rply.rj_vers.low;
error->re_vers.high = msg->rjcted_rply.rj_vers.high;
break;
case RPC_AUTHERROR:
error->re_why = msg->rjcted_rply.rj_why;
break;
case RPC_PROGVERSMISMATCH:
error->re_vers.low = msg->acpted_rply.ar_vers.low;
error->re_vers.high = msg->acpted_rply.ar_vers.high;
break;
case RPC_FAILED:
case RPC_SUCCESS:
case RPC_PROGNOTREGISTERED:
case RPC_PMAPFAILURE:
case RPC_UNKNOWNPROTO:
case RPC_UNKNOWNHOST:
case RPC_SYSTEMERROR:
case RPC_CANTDECODEARGS:
case RPC_PROCUNAVAIL:
case RPC_PROGUNAVAIL:
case RPC_TIMEDOUT:
case RPC_CANTRECV:
case RPC_CANTSEND:
case RPC_CANTDECODERES:
case RPC_CANTENCODEARGS:
default:
break;
}
}

642
libtirpc/src/rpc_soc.c Normal file
View file

@ -0,0 +1,642 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
* In addition, portions of such source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*/
#if defined(PORTMAP) || defined (_WIN32)
/*
* rpc_soc.c
*
* The backward compatibility routines for the earlier implementation
* of RPC, where the only transports supported were tcp/ip and udp/ip.
* Based on berkeley socket abstraction, now implemented on the top
* of TLI/Streams
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <reentrant.h>
#include <sys/types.h>
//#include <sys/socket.h>
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_prot.h>
#include <rpc/nettype.h>
//#include <syslog.h>
//#include <netinet/in.h>
//#include <netdb.h>
#include <errno.h>
//#include <syslog.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include "rpc_com.h"
extern mutex_t rpcsoc_lock;
static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
int *, u_int, u_int, char *);
static SVCXPRT *svc_com_create(SOCKET, u_int, u_int, char *);
static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
/* XXX */
#define IN4_LOCALHOST_STRING "127.0.0.1"
#define IN6_LOCALHOST_STRING "::1"
/*
* A common clnt create routine
*/
static CLIENT *
clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
struct sockaddr_in *raddr;
rpcprog_t prog;
rpcvers_t vers;
SOCKET *sockp;
u_int sendsz;
u_int recvsz;
char *tp;
{
CLIENT *cl;
int madefd = FALSE;
SOCKET fd = *sockp;
struct netconfig *nconf;
struct netbuf bindaddr;
mutex_lock(&rpcsoc_lock);
if ((nconf = __rpc_getconfip(tp)) == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
mutex_unlock(&rpcsoc_lock);
return (NULL);
}
if (fd == RPC_ANYSOCK) {
fd = __rpc_nconf2fd(nconf);
if (fd == -1)
goto syserror;
madefd = TRUE;
}
if (raddr->sin_port == 0) {
u_int proto;
u_short sport;
mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */
proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
proto);
if (sport == 0) {
goto err;
}
raddr->sin_port = htons(sport);
mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */
}
/* Transform sockaddr_in to netbuf */
bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in);
bindaddr.buf = raddr;
bindresvport(fd, NULL);
cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
sendsz, recvsz, NULL, NULL, NULL);
if (cl) {
if (madefd == TRUE) {
/*
* The fd should be closed while destroying the handle.
*/
(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
*sockp = fd;
}
(void) freenetconfigent(nconf);
mutex_unlock(&rpcsoc_lock);
return (cl);
}
goto err;
syserror:
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
err: if (madefd == TRUE)
(void)closesocket(fd);
(void) freenetconfigent(nconf);
mutex_unlock(&rpcsoc_lock);
return (NULL);
}
CLIENT *
clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
struct sockaddr_in *raddr;
u_long prog;
u_long vers;
struct timeval wait;
int *sockp;
u_int sendsz;
u_int recvsz;
{
CLIENT *cl;
cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
sendsz, recvsz, "udp");
if (cl == NULL) {
return (NULL);
}
(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
return (cl);
}
CLIENT *
clntudp_create(raddr, program, version, wait, sockp)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
int *sockp;
{
return clntudp_bufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE);
}
CLIENT *
clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
struct sockaddr_in *raddr;
u_long prog;
u_long vers;
int *sockp;
u_int sendsz;
u_int recvsz;
{
return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
sendsz, recvsz, "tcp");
}
/* IPv6 version of clnt*_*create */
#ifdef INET6_NOT_USED
CLIENT *
clntudp6_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
struct sockaddr_in6 *raddr;
u_long prog;
u_long vers;
struct timeval wait;
int *sockp;
u_int sendsz;
u_int recvsz;
{
CLIENT *cl;
cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
sendsz, recvsz, "udp6");
if (cl == NULL) {
return (NULL);
}
(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
return (cl);
}
CLIENT *
clntudp6_create(raddr, program, version, wait, sockp)
struct sockaddr_in6 *raddr;
u_long program;
u_long version;
struct timeval wait;
int *sockp;
{
return clntudp6_bufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE);
}
CLIENT *
clnttcp6_create(raddr, prog, vers, sockp, sendsz, recvsz)
struct sockaddr_in6 *raddr;
u_long prog;
u_long vers;
int *sockp;
u_int sendsz;
u_int recvsz;
{
return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
sendsz, recvsz, "tcp6");
}
#endif
CLIENT *
clntraw_create(prog, vers)
u_long prog;
u_long vers;
{
return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
}
/*
* A common server create routine
*/
static SVCXPRT *
svc_com_create(fd, sendsize, recvsize, netid)
SOCKET fd;
u_int sendsize;
u_int recvsize;
char *netid;
{
struct netconfig *nconf;
SVCXPRT *svc;
int madefd = FALSE;
int port;
struct sockaddr_in sin;
if ((nconf = __rpc_getconfip(netid)) == NULL) {
//(void) syslog(LOG_ERR, "Could not get %s transport", netid);
return (NULL);
}
if (fd == RPC_ANYSOCK) {
fd = __rpc_nconf2fd(nconf);
if (fd == -1) {
(void) freenetconfigent(nconf);
//(void) syslog(LOG_ERR,
//"svc%s_create: could not open connection", netid);
return (NULL);
}
madefd = TRUE;
}
memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
bindresvport(fd, &sin);
listen(fd, SOMAXCONN);
svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
(void) freenetconfigent(nconf);
if (svc == NULL) {
if (madefd)
(void)closesocket(fd);
return (NULL);
}
port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
svc->xp_port = ntohs((u_short)port);
return (svc);
}
SVCXPRT *
svctcp_create(fd, sendsize, recvsize)
SOCKET fd;
u_int sendsize;
u_int recvsize;
{
return svc_com_create(fd, sendsize, recvsize, "tcp");
}
SVCXPRT *
svcudp_bufcreate(fd, sendsz, recvsz)
SOCKET fd;
u_int sendsz, recvsz;
{
return svc_com_create(fd, sendsz, recvsz, "udp");
}
SVCXPRT *
svcfd_create(fd, sendsize, recvsize)
SOCKET fd;
u_int sendsize;
u_int recvsize;
{
return svc_fd_create(fd, sendsize, recvsize);
}
SVCXPRT *
svcudp_create(fd)
SOCKET fd;
{
return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
}
SVCXPRT *
svcraw_create()
{
return svc_raw_create();
}
/* IPV6 version */
#ifdef INET6_NOT_USED
SVCXPRT *
svcudp6_bufcreate(fd, sendsz, recvsz)
int fd;
u_int sendsz, recvsz;
{
return svc_com_create(fd, sendsz, recvsz, "udp6");
}
SVCXPRT *
svctcp6_create(fd, sendsize, recvsize)
int fd;
u_int sendsize;
u_int recvsize;
{
return svc_com_create(fd, sendsize, recvsize, "tcp6");
}
SVCXPRT *
svcudp6_create(fd)
int fd;
{
return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp6");
}
#endif
int
get_myaddress(addr)
struct sockaddr_in *addr;
{
memset((void *) addr, 0, sizeof(*addr));
addr->sin_family = AF_INET;
addr->sin_port = htons(PMAPPORT);
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
return (0);
}
/*
* For connectionless "udp" transport. Obsoleted by rpc_call().
*/
int
callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
const char *host;
int prognum, versnum, procnum;
xdrproc_t inproc, outproc;
void *in, *out;
{
return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
(rpcproc_t)procnum, inproc, in, outproc, out, "udp");
}
/*
* For connectionless kind of transport. Obsoleted by rpc_reg()
*/
int
registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
int prognum, versnum, procnum;
char *(*progname)(char [UDPMSGSIZE]);
xdrproc_t inproc, outproc;
{
return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
(rpcproc_t)procnum, progname, inproc, outproc, "udp");
}
/*
* All the following clnt_broadcast stuff is convulated; it supports
* the earlier calling style of the callback function
*/
extern thread_key_t clnt_broadcast_key;
/*
* Need to translate the netbuf address into sockaddr_in address.
* Dont care about netid here.
*/
/* ARGSUSED */
static bool_t
rpc_wrap_bcast(resultp, addr, nconf)
char *resultp; /* results of the call */
struct netbuf *addr; /* address of the guy who responded */
struct netconfig *nconf; /* Netconf of the transport */
{
resultproc_t clnt_broadcast_result;
if (strcmp(nconf->nc_netid, "udp"))
return (FALSE);
clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
return (*clnt_broadcast_result)(resultp,
(struct sockaddr_in *)addr->buf);
}
/*
* Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
*/
enum clnt_stat
clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
u_long prog; /* program number */
u_long vers; /* version number */
u_long proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
void *argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
void *resultsp; /* pointer to results */
resultproc_t eachresult; /* call with each result obtained */
{
extern mutex_t tsd_lock;
if (clnt_broadcast_key == -1) {
mutex_lock(&tsd_lock);
if (clnt_broadcast_key == -1)
thr_keycreate(&clnt_broadcast_key, free);
mutex_unlock(&tsd_lock);
}
thr_setspecific(clnt_broadcast_key, (void *) eachresult);
return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
(rpcproc_t)proc, xargs, argsp, xresults, resultsp,
(resultproc_t) rpc_wrap_bcast, "udp");
}
#ifndef _WIN32
/*
* Create the client des authentication object. Obsoleted by
* authdes_seccreate().
*/
AUTH *
authdes_create(servername, window, syncaddr, ckey)
char *servername; /* network name of server */
u_int window; /* time to live */
struct sockaddr *syncaddr; /* optional hostaddr to sync with */
des_block *ckey; /* optional conversation key to use */
{
AUTH *dummy;
AUTH *nauth;
char hostname[NI_MAXHOST];
if (syncaddr) {
/*
* Change addr to hostname, because that is the way
* new interface takes it.
*/
if (getnameinfo(syncaddr, sizeof(syncaddr), hostname,
sizeof hostname, NULL, 0, 0) != 0)
goto fallback;
nauth = authdes_seccreate(servername, window, hostname, ckey);
return (nauth);
}
fallback:
dummy = authdes_seccreate(servername, window, NULL, ckey);
return (dummy);
}
#endif
/*
* Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
*/
CLIENT *
clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
struct sockaddr_un *raddr;
u_long prog;
u_long vers;
SOCKET *sockp;
u_int sendsz;
u_int recvsz;
{
struct netbuf *svcaddr;
struct netconfig *nconf;
CLIENT *cl;
int len;
cl = NULL;
nconf = NULL;
svcaddr = NULL;
if (((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
if (svcaddr != NULL)
free(svcaddr);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
return(cl);
}
if (*sockp == SOCKET_ERROR) {
*sockp = socket(AF_UNIX, SOCK_STREAM, 0);
len = SUN_LEN(raddr);
if ((*sockp == INVALID_SOCKET) || (connect(*sockp,
(struct sockaddr *)raddr, len) == SOCKET_ERROR)) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
if (*sockp != INVALID_SOCKET)
(void)closesocket(*sockp);
goto done;
}
}
svcaddr->buf = raddr;
svcaddr->len = sizeof(raddr);
svcaddr->maxlen = sizeof (struct sockaddr_un);
cl = clnt_vc_create(*sockp, svcaddr, prog,
vers, sendsz, recvsz, NULL, NULL, NULL);
done:
free(svcaddr->buf);
free(svcaddr);
return(cl);
}
/*
* Creates, registers, and returns a (rpc) unix based transporter.
* Obsoleted by svc_vc_create().
*/
SVCXPRT *
svcunix_create(sock, sendsize, recvsize, path)
SOCKET sock;
u_int sendsize;
u_int recvsize;
char *path;
{
struct netconfig *nconf;
void *localhandle;
struct sockaddr_un sun;
struct sockaddr *sa;
struct t_bind taddr;
SVCXPRT *xprt;
int addrlen;
xprt = (SVCXPRT *)NULL;
localhandle = setnetconfig();
while ((nconf = getnetconfig(localhandle)) != NULL) {
if (nconf->nc_protofmly != NULL &&
strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
break;
}
if (nconf == NULL)
return(xprt);
if ((sock = __rpc_nconf2fd(nconf)) == SOCKET_ERROR)
goto done;
memset(&sun, 0, sizeof sun);
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, path, sizeof(sun.sun_path));
addrlen = sizeof(struct sockaddr_un);
sa = (struct sockaddr *)&sun;
if (bind(sock, sa, addrlen) == SOCKET_ERROR)
goto done;
taddr.addr.len = taddr.addr.maxlen = addrlen;
taddr.addr.buf = malloc(addrlen);
if (taddr.addr.buf == NULL)
goto done;
memcpy(taddr.addr.buf, sa, addrlen);
if (nconf->nc_semantics != NC_TPI_CLTS) {
if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
free(taddr.addr.buf);
goto done;
}
}
xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);
done:
endnetconfig(localhandle);
return(xprt);
}
/*
* Like svunix_create(), except the routine takes any *open* UNIX file
* descriptor as its first input. Obsoleted by svc_fd_create();
*/
SVCXPRT *
svcunixfd_create(fd, sendsize, recvsize)
SOCKET fd;
u_int sendsize;
u_int recvsize;
{
return (svc_fd_create(fd, sendsize, recvsize));
}
#endif /* PORTMAP */

1240
libtirpc/src/rpcb_clnt.c Normal file

File diff suppressed because it is too large Load diff

319
libtirpc/src/rpcb_prot.c Normal file
View file

@ -0,0 +1,319 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
/*
* rpcb_prot.c
* XDR routines for the rpcbinder version 3.
*
* Copyright (C) 1984, 1988, Sun Microsystems, Inc.
*/
#include <wintirpc.h>
#include <rpc/rpc.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/rpcb_prot.h>
bool_t
xdr_rpcb(xdrs, objp)
XDR *xdrs;
RPCB *objp;
{
if (!xdr_u_int32_t(xdrs, &objp->r_prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->r_vers)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) {
return (FALSE);
}
return (TRUE);
}
/*
* rpcblist_ptr implements a linked list. The RPCL definition from
* rpcb_prot.x is:
*
* struct rpcblist {
* rpcb rpcb_map;
* struct rpcblist *rpcb_next;
* };
* typedef rpcblist *rpcblist_ptr;
*
* Recall that "pointers" in XDR are encoded as a boolean, indicating whether
* there's any data behind the pointer, followed by the data (if any exists).
* The boolean can be interpreted as ``more data follows me''; if FALSE then
* nothing follows the boolean; if TRUE then the boolean is followed by an
* actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
* rpcblist *").
*
* This could be implemented via the xdr_pointer type, though this would
* result in one recursive call per element in the list. Rather than do that
* we can ``unwind'' the recursion into a while loop and use xdr_reference to
* serialize the rpcb elements.
*/
bool_t
xdr_rpcblist_ptr(xdrs, rp)
XDR *xdrs;
rpcblist_ptr *rp;
{
/*
* more_elements is pre-computed in case the direction is
* XDR_ENCODE or XDR_FREE. more_elements is overwritten by
* xdr_bool when the direction is XDR_DECODE.
*/
bool_t more_elements;
int freeing = (xdrs->x_op == XDR_FREE);
rpcblist_ptr next;
rpcblist_ptr next_copy;
next = NULL;
for (;;) {
more_elements = (bool_t)(*rp != NULL);
if (! xdr_bool(xdrs, &more_elements)) {
return (FALSE);
}
if (! more_elements) {
return (TRUE); /* we are done */
}
/*
* the unfortunate side effect of non-recursion is that in
* the case of freeing we must remember the next object
* before we free the current object ...
*/
if (freeing)
next = (*rp)->rpcb_next;
if (! xdr_reference(xdrs, (caddr_t *)rp,
(u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
return (FALSE);
}
if (freeing) {
next_copy = next;
rp = &next_copy;
/*
* Note that in the subsequent iteration, next_copy
* gets nulled out by the xdr_reference
* but next itself survives.
*/
} else {
rp = &((*rp)->rpcb_next);
}
}
/*NOTREACHED*/
}
/*
* xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
* functionality to xdr_rpcblist_ptr().
*/
bool_t
xdr_rpcblist(xdrs, rp)
XDR *xdrs;
RPCBLIST **rp;
{
bool_t dummy;
dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
return (dummy);
}
bool_t
xdr_rpcb_entry(xdrs, objp)
XDR *xdrs;
rpcb_entry *objp;
{
if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_rpcb_entry_list_ptr(xdrs, rp)
XDR *xdrs;
rpcb_entry_list_ptr *rp;
{
/*
* more_elements is pre-computed in case the direction is
* XDR_ENCODE or XDR_FREE. more_elements is overwritten by
* xdr_bool when the direction is XDR_DECODE.
*/
bool_t more_elements;
int freeing = (xdrs->x_op == XDR_FREE);
rpcb_entry_list_ptr next;
rpcb_entry_list_ptr next_copy;
next = NULL;
for (;;) {
more_elements = (bool_t)(*rp != NULL);
if (! xdr_bool(xdrs, &more_elements)) {
return (FALSE);
}
if (! more_elements) {
return (TRUE); /* we are done */
}
/*
* the unfortunate side effect of non-recursion is that in
* the case of freeing we must remember the next object
* before we free the current object ...
*/
if (freeing)
next = (*rp)->rpcb_entry_next;
if (! xdr_reference(xdrs, (caddr_t *)rp,
(u_int)sizeof (rpcb_entry_list),
(xdrproc_t)xdr_rpcb_entry)) {
return (FALSE);
}
if (freeing) {
next_copy = next;
rp = &next_copy;
/*
* Note that in the subsequent iteration, next_copy
* gets nulled out by the xdr_reference
* but next itself survives.
*/
} else {
rp = &((*rp)->rpcb_entry_next);
}
}
/*NOTREACHED*/
}
/*
* XDR remote call arguments
* written for XDR_ENCODE direction only
*/
bool_t
xdr_rpcb_rmtcallargs(xdrs, p)
XDR *xdrs;
struct rpcb_rmtcallargs *p;
{
struct r_rpcb_rmtcallargs *objp =
(struct r_rpcb_rmtcallargs *)(void *)p;
u_int lenposition, argposition, position;
int32_t *buf;
buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
return (FALSE);
}
} else {
IXDR_PUT_U_INT32(buf, objp->prog);
IXDR_PUT_U_INT32(buf, objp->vers);
IXDR_PUT_U_INT32(buf, objp->proc);
}
/*
* All the jugglery for just getting the size of the arguments
*/
lenposition = XDR_GETPOS(xdrs);
if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
return (FALSE);
}
argposition = XDR_GETPOS(xdrs);
if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
return (FALSE);
}
position = XDR_GETPOS(xdrs);
objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
XDR_SETPOS(xdrs, lenposition);
if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
return (FALSE);
}
XDR_SETPOS(xdrs, position);
return (TRUE);
}
/*
* XDR remote call results
* written for XDR_DECODE direction only
*/
bool_t
xdr_rpcb_rmtcallres(xdrs, p)
XDR *xdrs;
struct rpcb_rmtcallres *p;
{
bool_t dummy;
struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) {
return (FALSE);
}
if (!xdr_u_int(xdrs, &objp->results.results_len)) {
return (FALSE);
}
dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
return (dummy);
}
bool_t
xdr_netbuf(xdrs, objp)
XDR *xdrs;
struct netbuf *objp;
{
bool_t dummy;
if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
return (FALSE);
}
dummy = xdr_bytes(xdrs, (char **)&(objp->buf),
(u_int *)&(objp->len), objp->maxlen);
return (dummy);
}

265
libtirpc/src/rpcb_st_xdr.c Normal file
View file

@ -0,0 +1,265 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright 1991 Sun Microsystems, Inc.
* rpcb_stat_xdr.c
*/
/*
* This file was generated from rpcb_prot.x, but includes only those
* routines used with the rpcbind stats facility.
*/
//#include <sys/cdefs.h>
#include <wintirpc.h>
#include <rpc/rpc.h>
/* Link list of all the stats about getport and getaddr */
bool_t
xdr_rpcbs_addrlist(xdrs, objp)
XDR *xdrs;
rpcbs_addrlist *objp;
{
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->success)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->failure)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **)&objp->next,
sizeof (rpcbs_addrlist),
(xdrproc_t)xdr_rpcbs_addrlist)) {
return (FALSE);
}
return (TRUE);
}
/* Link list of all the stats about rmtcall */
bool_t
xdr_rpcbs_rmtcalllist(xdrs, objp)
XDR *xdrs;
rpcbs_rmtcalllist *objp;
{
int32_t *buf;
if (xdrs->x_op == XDR_ENCODE) {
buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->success)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->failure)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->indirect)) {
return (FALSE);
}
} else {
IXDR_PUT_U_INT32(buf, objp->prog);
IXDR_PUT_U_INT32(buf, objp->vers);
IXDR_PUT_U_INT32(buf, objp->proc);
IXDR_PUT_INT32(buf, objp->success);
IXDR_PUT_INT32(buf, objp->failure);
IXDR_PUT_INT32(buf, objp->indirect);
}
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **)&objp->next,
sizeof (rpcbs_rmtcalllist),
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
return (FALSE);
}
return (TRUE);
} else if (xdrs->x_op == XDR_DECODE) {
buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->success)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->failure)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->indirect)) {
return (FALSE);
}
} else {
objp->prog = (rpcprog_t)IXDR_GET_U_INT32(buf);
objp->vers = (rpcvers_t)IXDR_GET_U_INT32(buf);
objp->proc = (rpcproc_t)IXDR_GET_U_INT32(buf);
objp->success = (int)IXDR_GET_INT32(buf);
objp->failure = (int)IXDR_GET_INT32(buf);
objp->indirect = (int)IXDR_GET_INT32(buf);
}
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **)&objp->next,
sizeof (rpcbs_rmtcalllist),
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
return (FALSE);
}
return (TRUE);
}
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
return (FALSE);
}
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->success)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->failure)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->indirect)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **)&objp->next,
sizeof (rpcbs_rmtcalllist),
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_rpcbs_proc(xdrs, objp)
XDR *xdrs;
rpcbs_proc objp;
{
if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBSTAT_HIGHPROC,
sizeof (int), (xdrproc_t)xdr_int)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_rpcbs_addrlist_ptr(xdrs, objp)
XDR *xdrs;
rpcbs_addrlist_ptr *objp;
{
if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_addrlist),
(xdrproc_t)xdr_rpcbs_addrlist)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_rpcbs_rmtcalllist_ptr(xdrs, objp)
XDR *xdrs;
rpcbs_rmtcalllist_ptr *objp;
{
if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_rmtcalllist),
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_rpcb_stat(xdrs, objp)
XDR *xdrs;
rpcb_stat *objp;
{
if (!xdr_rpcbs_proc(xdrs, objp->info)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->setinfo)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->unsetinfo)) {
return (FALSE);
}
if (!xdr_rpcbs_addrlist_ptr(xdrs, &objp->addrinfo)) {
return (FALSE);
}
if (!xdr_rpcbs_rmtcalllist_ptr(xdrs, &objp->rmtinfo)) {
return (FALSE);
}
return (TRUE);
}
/*
* One rpcb_stat structure is returned for each version of rpcbind
* being monitored.
*/
bool_t
xdr_rpcb_stat_byvers(xdrs, objp)
XDR *xdrs;
rpcb_stat_byvers objp;
{
if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBVERS_STAT,
sizeof (rpcb_stat), (xdrproc_t)xdr_rpcb_stat)) {
return (FALSE);
}
return (TRUE);
}

78
libtirpc/src/rpcdname.c Normal file
View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/cdefs.h>
/*
* rpcdname.c
* Gets the default domain name
*/
#include <wintirpc.h>
#include <stdlib.h>
//#include <unistd.h>
#include <string.h>
static char *default_domain = NULL;
static char *
get_default_domain()
{
#ifndef _WIN32
char temp[256];
#endif
if (default_domain)
return (default_domain);
#ifndef _WIN32 // Need a WIN32 version?
if (getdomainname(temp, sizeof(temp)) < 0)
return (0);
if ((int) strlen(temp) > 0) {
default_domain = (char *)malloc((strlen(temp)+(unsigned)1));
if (default_domain == 0)
return (NULL);
(void) strcpy(default_domain, temp);
return (default_domain);
}
#endif
return (NULL);
}
/*
* This is a wrapper for the system call getdomainname which returns a
* ypclnt.h error code in the failure case. It also checks to see that
* the domain name is non-null, knowing that the null string is going to
* get rejected elsewhere in the NIS client package.
*/
int
__rpc_get_default_domain(domain)
char **domain;
{
if ((*domain = get_default_domain()) != 0)
return (0);
return (-1);
}

154
libtirpc/src/rtime.c Normal file
View file

@ -0,0 +1,154 @@
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* rtime - get time from remote machine
*
* gets time, obtaining value from host
* on the udp/time socket. Since timeserver returns
* with time of day in seconds since Jan 1, 1900, must
* subtract seconds before Jan 1, 1970 to get
* what unix uses.
*/
#include <wintirpc.h>
//#include <pthread.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <sys/time.h>
//#include <netinet/in.h>
#include <stdio.h>
//#include <netdb.h>
//#include <sys/select.h>
extern int _rpc_dtablesize( void );
#define NYEARS (unsigned long)(1970 - 1900)
#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4)))
static void do_close( SOCKET );
int
rtime(addrp, timep, timeout)
struct sockaddr_in *addrp;
struct timeval *timep;
struct timeval *timeout;
{
SOCKET s;
fd_set readfds;
int res;
unsigned long thetime;
struct sockaddr_in from;
int fromlen;
int type;
struct servent *serv;
if (timeout == NULL) {
type = SOCK_STREAM;
} else {
type = SOCK_DGRAM;
}
s = socket(AF_INET, type, 0);
if (s == INVALID_SOCKET) {
return(-1);
}
addrp->sin_family = AF_INET;
/* TCP and UDP port are the same in this case */
if ((serv = getservbyname("time", "tcp")) == NULL) {
return(-1);
}
addrp->sin_port = serv->s_port;
if (type == SOCK_DGRAM) {
res = sendto(s, (char *)&thetime, sizeof(thetime), 0,
(struct sockaddr *)addrp, sizeof(*addrp));
if (res == SOCKET_ERROR) {
do_close(s);
return(-1);
}
do {
FD_ZERO(&readfds);
FD_SET(s, &readfds);
res = select(_rpc_dtablesize(), &readfds,
(fd_set *)NULL, (fd_set *)NULL, timeout);
} while (res == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
if (res == 0 || res == SOCKET_ERROR) {
if (res == 0) {
errno = WSAETIMEDOUT;
}
do_close(s);
return(-1);
}
fromlen = sizeof(from);
res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
(struct sockaddr *)&from, &fromlen);
do_close(s);
if (res == SOCKET_ERROR) {
return(-1);
}
} else {
if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) == SOCKET_ERROR) {
do_close(s);
return(-1);
}
res = recv(s, (char *)&thetime, sizeof(thetime), 0);
do_close(s);
if (res == SOCKET_ERROR) {
return(-1);
}
}
if (res != sizeof(thetime)) {
errno = EIO;
return(-1);
}
thetime = ntohl(thetime);
timep->tv_sec = thetime - TOFFSET;
timep->tv_usec = 0;
return(0);
}
static void
do_close(s)
int s;
{
int save;
save = errno;
(void)closesocket(s);
errno = save;
}

Some files were not shown because too many files have changed in this diff Show more