summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred Perlstein <alfred@FreeBSD.org>2001-03-19 12:50:13 +0000
committerAlfred Perlstein <alfred@FreeBSD.org>2001-03-19 12:50:13 +0000
commit8360efbd6c932013ffdb2f83d2f2de4278febb5e (patch)
treeb842b4bf2665ef953be005b10013a2f3daf323c3
parent1ac2b9fe972a0c73729565f8310fa6eba55718c4 (diff)
downloadsrc-test2-8360efbd6c932013ffdb2f83d2f2de4278febb5e.tar.gz
src-test2-8360efbd6c932013ffdb2f83d2f2de4278febb5e.zip
Notes
-rw-r--r--etc/Makefile2
-rw-r--r--etc/defaults/rc.conf32
-rw-r--r--etc/netconfig17
-rw-r--r--etc/network.subr230
-rw-r--r--etc/rc.d/netoptions230
-rw-r--r--etc/rc.d/network1230
-rw-r--r--etc/rc.d/network2230
-rw-r--r--etc/rc.d/network3230
-rw-r--r--etc/rc.d/routing230
-rw-r--r--etc/rc.network230
-rw-r--r--etc/rpc37
-rw-r--r--include/Makefile11
-rw-r--r--include/netconfig.h96
-rw-r--r--include/pthread_np.h2
-rw-r--r--include/rpc/Makefile37
-rw-r--r--include/rpc/auth.h242
-rw-r--r--include/rpc/auth_des.h19
-rw-r--r--include/rpc/auth_kerb.h143
-rw-r--r--include/rpc/clnt.h438
-rw-r--r--include/rpc/clnt_soc.h118
-rw-r--r--include/rpc/clnt_stat.h83
-rw-r--r--include/rpc/des_crypt.h42
-rw-r--r--include/rpc/nettype.h64
-rw-r--r--include/rpc/pmap_clnt.h13
-rw-r--r--include/rpc/pmap_prot.h11
-rw-r--r--include/rpc/pmap_rmt.h8
-rw-r--r--include/rpc/raw.h58
-rw-r--r--include/rpc/rpc.h51
-rw-r--r--include/rpc/rpc_com.h55
-rw-r--r--include/rpc/rpc_msg.h44
-rw-r--r--include/rpc/rpcb_clnt.h85
-rw-r--r--include/rpc/rpcb_prot.x554
-rw-r--r--include/rpc/rpcent.h69
-rw-r--r--include/rpc/svc.h217
-rw-r--r--include/rpc/svc_auth.h19
-rw-r--r--include/rpc/svc_dg.h51
-rw-r--r--include/rpc/svc_soc.h116
-rw-r--r--include/rpc/types.h58
-rw-r--r--include/rpc/xdr.h112
-rw-r--r--include/rpcsvc/key_prot.x2
-rw-r--r--include/rpcsvc/nlm_prot.x151
-rw-r--r--include/rpcsvc/sm_inter.x5
-rw-r--r--lib/libc/gen/_pthread_stubs.c93
-rw-r--r--lib/libc/include/namespace.h16
-rw-r--r--lib/libc/include/reentrant.h130
-rw-r--r--lib/libc/rpc/DISCLAIMER3
-rw-r--r--lib/libc/rpc/Makefile.inc218
-rw-r--r--lib/libc/rpc/README361
-rw-r--r--lib/libc/rpc/auth_des.c378
-rw-r--r--lib/libc/rpc/auth_none.c112
-rw-r--r--lib/libc/rpc/auth_time.c11
-rw-r--r--lib/libc/rpc/auth_unix.c218
-rw-r--r--lib/libc/rpc/authdes_prot.c23
-rw-r--r--lib/libc/rpc/authunix_prot.c20
-rw-r--r--lib/libc/rpc/bindresvport.3109
-rw-r--r--lib/libc/rpc/bindresvport.c46
-rw-r--r--lib/libc/rpc/clnt_bcast.c667
-rw-r--r--lib/libc/rpc/clnt_dg.c821
-rw-r--r--lib/libc/rpc/clnt_generic.c362
-rw-r--r--lib/libc/rpc/clnt_perror.c150
-rw-r--r--lib/libc/rpc/clnt_raw.c188
-rw-r--r--lib/libc/rpc/clnt_simple.c189
-rw-r--r--lib/libc/rpc/clnt_tcp.c582
-rw-r--r--lib/libc/rpc/clnt_udp.c569
-rw-r--r--lib/libc/rpc/clnt_unix.c637
-rw-r--r--lib/libc/rpc/clnt_vc.c839
-rw-r--r--lib/libc/rpc/crypt_client.c4
-rw-r--r--lib/libc/rpc/get_myaddress.c114
-rw-r--r--lib/libc/rpc/getnetconfig.3182
-rw-r--r--lib/libc/rpc/getnetconfig.c674
-rw-r--r--lib/libc/rpc/getnetpath.3154
-rw-r--r--lib/libc/rpc/getnetpath.c273
-rw-r--r--lib/libc/rpc/getpublickey.c2
-rw-r--r--lib/libc/rpc/getrpcent.332
-rw-r--r--lib/libc/rpc/getrpcent.c55
-rw-r--r--lib/libc/rpc/getrpcport.32
-rw-r--r--lib/libc/rpc/getrpcport.c27
-rw-r--r--lib/libc/rpc/key_call.c89
-rw-r--r--lib/libc/rpc/key_prot_xdr.c6
-rw-r--r--lib/libc/rpc/mt_misc.c125
-rw-r--r--lib/libc/rpc/netconfig.5126
-rw-r--r--lib/libc/rpc/netname.c10
-rw-r--r--lib/libc/rpc/netnamer.c2
-rw-r--r--lib/libc/rpc/pmap_clnt.c123
-rw-r--r--lib/libc/rpc/pmap_getmaps.c40
-rw-r--r--lib/libc/rpc/pmap_getport.c36
-rw-r--r--lib/libc/rpc/pmap_prot.c14
-rw-r--r--lib/libc/rpc/pmap_prot2.c43
-rw-r--r--lib/libc/rpc/pmap_rmt.c332
-rw-r--r--lib/libc/rpc/rpc.31992
-rw-r--r--lib/libc/rpc/rpc.550
-rw-r--r--lib/libc/rpc/rpc_callmsg.c70
-rw-r--r--lib/libc/rpc/rpc_clnt_auth.395
-rw-r--r--lib/libc/rpc/rpc_clnt_calls.3302
-rw-r--r--lib/libc/rpc/rpc_clnt_create.3437
-rw-r--r--lib/libc/rpc/rpc_com.h85
-rw-r--r--lib/libc/rpc/rpc_commondata.c21
-rw-r--r--lib/libc/rpc/rpc_dtablesize.c8
-rw-r--r--lib/libc/rpc/rpc_generic.c816
-rw-r--r--lib/libc/rpc/rpc_prot.c140
-rw-r--r--lib/libc/rpc/rpc_soc.31810
-rw-r--r--lib/libc/rpc/rpc_soc.c453
-rw-r--r--lib/libc/rpc/rpc_svc_calls.3263
-rw-r--r--lib/libc/rpc/rpc_svc_create.3622
-rw-r--r--lib/libc/rpc/rpc_svc_err.395
-rw-r--r--lib/libc/rpc/rpc_svc_reg.3183
-rw-r--r--lib/libc/rpc/rpc_xdr.3101
-rw-r--r--lib/libc/rpc/rpcb_clnt.c1253
-rw-r--r--lib/libc/rpc/rpcb_prot.c329
-rw-r--r--lib/libc/rpc/rpcb_st_xdr.c265
-rw-r--r--lib/libc/rpc/rpcbind.3189
-rw-r--r--lib/libc/rpc/rpcdname.c3
-rw-r--r--lib/libc/rpc/svc.c583
-rw-r--r--lib/libc/rpc/svc_auth.c91
-rw-r--r--lib/libc/rpc/svc_auth_des.c5
-rw-r--r--lib/libc/rpc/svc_auth_unix.c54
-rw-r--r--lib/libc/rpc/svc_dg.c603
-rw-r--r--lib/libc/rpc/svc_generic.c313
-rw-r--r--lib/libc/rpc/svc_raw.c212
-rw-r--r--lib/libc/rpc/svc_run.c58
-rw-r--r--lib/libc/rpc/svc_simple.c279
-rw-r--r--lib/libc/rpc/svc_tcp.c487
-rw-r--r--lib/libc/rpc/svc_udp.c482
-rw-r--r--lib/libc/rpc/svc_unix.c533
-rw-r--r--lib/libc/rpc/svc_vc.c689
-rw-r--r--lib/libc/xdr/Makefile.inc15
-rw-r--r--lib/libc/xdr/xdr.387
-rw-r--r--lib/libc/xdr/xdr.c321
-rw-r--r--lib/libc/xdr/xdr_array.c50
-rw-r--r--lib/libc/xdr/xdr_float.c89
-rw-r--r--lib/libc/xdr/xdr_mem.c136
-rw-r--r--lib/libc/xdr/xdr_rec.c256
-rw-r--r--lib/libc/xdr/xdr_reference.c31
-rw-r--r--lib/libc/xdr/xdr_sizeof.c4
-rw-r--r--lib/libc/xdr/xdr_stdio.c63
-rw-r--r--lib/libc_r/uthread/Makefile.inc1
-rw-r--r--lib/libc_r/uthread/uthread_main_np.c (renamed from usr.sbin/portmap/pmap_check.h)34
-rw-r--r--lib/libkse/thread/Makefile.inc1
-rw-r--r--lib/libkse/thread/thr_main_np.c45
-rw-r--r--lib/libpthread/thread/Makefile.inc1
-rw-r--r--lib/libpthread/thread/thr_main_np.c45
-rw-r--r--lib/librpcsvc/Makefile2
-rw-r--r--lib/librpcsvc/yp_passwd.c2
-rw-r--r--sbin/mount_nfs/mount_nfs.c296
-rw-r--r--sbin/mountd/mountd.c876
-rw-r--r--sbin/nfsd/nfsd.824
-rw-r--r--sbin/nfsd/nfsd.c823
-rw-r--r--sbin/umount/umount.c195
-rw-r--r--sys/rpc/types.h58
-rw-r--r--usr.bin/keylogin/keylogin.c3
-rw-r--r--usr.bin/rpcgen/rpc_main.c13
-rw-r--r--usr.bin/rpcgen/rpc_parse.c10
-rw-r--r--usr.bin/rpcgen/rpc_svcout.c4
-rw-r--r--usr.bin/rpcgen/rpcgen.114
-rw-r--r--usr.bin/rpcinfo/Makefile10
-rw-r--r--usr.bin/rpcinfo/rpcinfo.8404
-rw-r--r--usr.bin/rpcinfo/rpcinfo.c1836
-rw-r--r--usr.bin/rup/rup.c4
-rw-r--r--usr.bin/rusers/rusers.c4
-rw-r--r--usr.sbin/Makefile2
-rw-r--r--usr.sbin/bootparamd/callbootd/callbootd.c10
-rw-r--r--usr.sbin/keyserv/keyserv.c49
-rw-r--r--usr.sbin/mountd/mountd.c876
-rw-r--r--usr.sbin/nfsd/nfsd.824
-rw-r--r--usr.sbin/nfsd/nfsd.c823
-rw-r--r--usr.sbin/portmap/Makefile13
-rw-r--r--usr.sbin/portmap/from_local.c233
-rw-r--r--usr.sbin/portmap/pmap_check.c263
-rw-r--r--usr.sbin/portmap/pmap_dump/Makefile7
-rw-r--r--usr.sbin/portmap/pmap_dump/pmap_dump.c69
-rw-r--r--usr.sbin/portmap/pmap_set/Makefile7
-rw-r--r--usr.sbin/portmap/pmap_set/pmap_set.c78
-rw-r--r--usr.sbin/portmap/portmap.8122
-rw-r--r--usr.sbin/portmap/portmap.c612
-rw-r--r--usr.sbin/rpc.lockd/Makefile22
-rw-r--r--usr.sbin/rpc.lockd/lock_proc.c1294
-rw-r--r--usr.sbin/rpc.lockd/lockd.c231
-rw-r--r--usr.sbin/rpc.lockd/lockd.h17
-rw-r--r--usr.sbin/rpc.lockd/lockd_lock.c759
-rw-r--r--usr.sbin/rpc.lockd/lockd_lock.h21
-rw-r--r--usr.sbin/rpc.lockd/rpc.lockd.887
-rw-r--r--usr.sbin/rpc.lockd/test.c119
-rw-r--r--usr.sbin/rpc.statd/statd.h15
-rw-r--r--usr.sbin/rpc.umntall/rpc.umntall.c68
-rw-r--r--usr.sbin/rpc.yppasswdd/yppasswdd_main.c13
-rw-r--r--usr.sbin/rpc.ypupdated/ypupdated_extern.h1
-rw-r--r--usr.sbin/rpc.ypupdated/ypupdated_server.c1
-rw-r--r--usr.sbin/rpcbind/Makefile21
-rw-r--r--usr.sbin/rpcbind/check_bound.c229
-rw-r--r--usr.sbin/rpcbind/pmap_svc.c368
-rw-r--r--usr.sbin/rpcbind/rpcb_stat.c208
-rw-r--r--usr.sbin/rpcbind/rpcb_svc.c233
-rw-r--r--usr.sbin/rpcbind/rpcb_svc_4.c454
-rw-r--r--usr.sbin/rpcbind/rpcb_svc_com.c1457
-rw-r--r--usr.sbin/rpcbind/rpcbind.8112
-rw-r--r--usr.sbin/rpcbind/rpcbind.c568
-rw-r--r--usr.sbin/rpcbind/rpcbind.h144
-rw-r--r--usr.sbin/rpcbind/security.c283
-rw-r--r--usr.sbin/rpcbind/util.c381
-rw-r--r--usr.sbin/rpcbind/warmstart.c179
-rw-r--r--usr.sbin/ypbind/yp_ping.c4
-rw-r--r--usr.sbin/ypbind/ypbind.c2
-rw-r--r--usr.sbin/yppush/yppush_main.c6
-rw-r--r--usr.sbin/ypserv/yp_dnslookup.c4
204 files changed, 32019 insertions, 12077 deletions
diff --git a/etc/Makefile b/etc/Makefile
index 14814f5957e0..acc18d1a2afe 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -10,7 +10,7 @@ BIN1= amd.map apmd.conf auth.conf \
dhclient.conf dm.conf fbtab ftpusers gettytab group \
hosts hosts.allow hosts.equiv hosts.lpd \
inetd.conf login.access login.conf \
- motd modems networks newsyslog.conf \
+ motd modems netconfig networks newsyslog.conf \
pam.conf phones pim6dd.conf pim6sd.conf \
printcap profile protocols \
rc rc.atm rc.devfs rc.diskless1 rc.diskless2 rc.firewall rc.firewall6 \
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 3865a43818a4..d05dc7779afb 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -101,7 +101,7 @@ ppp_nat="YES" # Use PPP's internal network address translation or NO.
ppp_profile="papchap" # Which profile to use from /etc/ppp/ppp.conf.
ppp_user="root" # Which user to run ppp as
-### Network daemon (miscellaneous) & NFS options: ###
+### Network daemon (miscellaneous) ###
syslogd_enable="YES" # Run syslog daemon (or NO).
syslogd_flags="-s" # Flags to syslogd (if enabled).
inetd_enable="NO" # Run the network daemon dispatcher (YES/NO).
@@ -121,6 +121,19 @@ kadmind_server_enable="NO" # Run kadmind (or NO) -- do not run on
kerberos_stash="" # Is the kerberos master key stashed?
rwhod_enable="NO" # Run the rwho daemon (or NO).
rwhod_flags="" # Flags for rwhod
+rarpd_enable="NO" # Run rarpd (or NO).
+rarpd_flags="" # Flags to rarpd.
+xtend_enable="NO" # Run the X-10 power controller daemon.
+xtend_flags="" # Flags to xtend (if enabled).
+pppoed_enable="NO" # Run the PPP over Ethernet daemon.
+pppoed_provider="*" # Provider and ppp(8) config file entry.
+pppoed_flags="-P /var/run/pppoed.pid" # Flags to pppoed (if enabled).
+pppoed_interface="fxp0" # The interface that pppoed runs on.
+sshd_enable="NO" # Enable sshd
+sshd_program="/usr/sbin/sshd" # path to sshd, if you want a different one.
+sshd_flags="" # Additional flags for sshd.
+
+### Network daemon (NFS) Need all portmap_enable="YES" ###
amd_enable="NO" # Run amd service with $amd_flags (or NO).
amd_flags="-a /.amd_mnt -l syslog /host /etc/amd.map /net /etc/amd.map"
amd_map_program="NO" # Can be set to "ypcat -k amd.master"
@@ -135,24 +148,13 @@ weak_mountd_authentication="NO" # Allow non-root mount requests to be served.
nfs_reserved_port_only="NO" # Provide NFS only on secure port (or NO).
nfs_bufpackets="DEFAULT" # bufspace (in packets) for client (or DEFAULT)
rpc_lockd_enable="NO" # Run NFS rpc.lockd (*broken!*) if nfs_server.
-rpc_statd_enable="YES" # Run NFS rpc.statd if nfs_server (or NO).
+rpc_statd_enable="NO" # Run NFS rpc.statd if nfs_server (or NO).
portmap_enable="NO" # Run the portmapper service (YES/NO).
-portmap_program="/usr/sbin/portmap" # path to portmap, if you want a different one.
+portmap_program="/usr/sbin/rpcbind" # path to portmap, if you want a different one.
portmap_flags="" # Flags to portmap (if enabled).
rpc_ypupdated_enable="NO" # Run if NIS master and SecureRPC (or NO).
keyserv_enable="NO" # Run the SecureRPC keyserver (or NO).
keyserv_flags="" # Flags to keyserv (if enabled).
-rarpd_enable="NO" # Run rarpd (or NO).
-rarpd_flags="" # Flags to rarpd.
-xtend_enable="NO" # Run the X-10 power controller daemon.
-xtend_flags="" # Flags to xtend (if enabled).
-pppoed_enable="NO" # Run the PPP over Ethernet daemon.
-pppoed_provider="*" # Provider and ppp(8) config file entry.
-pppoed_flags="-P /var/run/pppoed.pid" # Flags to pppoed (if enabled).
-pppoed_interface="fxp0" # The interface that pppoed runs on.
-sshd_enable="NO" # Enable sshd
-sshd_program="/usr/sbin/sshd" # path to sshd, if you want a different one.
-sshd_flags="" # Additional flags for sshd.
### Network Time Services options: ###
timed_enable="NO" # Run the time daemon (or NO).
@@ -164,7 +166,7 @@ xntpd_enable="NO" # Run ntpd Network Time Protocol (or NO).
xntpd_program="ntpd" # path to ntpd, if you want a different one.
xntpd_flags="-p /var/run/ntpd.pid" # Flags to ntpd (if enabled).
-# Network Information Services (NIS) options: ###
+# Network Information Services (NIS) options: Need all portmap_enable="YES" ###
nis_client_enable="NO" # We're an NIS client (or NO).
nis_client_flags="" # Flags to ypbind (if enabled).
nis_ypset_enable="NO" # Run ypset at boot time (or NO).
diff --git a/etc/netconfig b/etc/netconfig
new file mode 100644
index 000000000000..89234fed6c73
--- /dev/null
+++ b/etc/netconfig
@@ -0,0 +1,17 @@
+# The network configuration file. This file is currently only used in
+# conjunction with the (TI-) RPC code in the C library, unlike its
+# use in SVR4.
+#
+# Entries consist of:
+#
+# <network_id> <semantics> <flags> <protofamily> <protoname> \
+# <device> <nametoaddr_libs>
+#
+# The <device> and <nametoaddr_libs> fields are always empty in FreeBSD.
+#
+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 - - -
+unix tpi_cots_ord - loopback - - -
diff --git a/etc/network.subr b/etc/network.subr
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/network.subr
+++ b/etc/network.subr
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.d/netoptions b/etc/rc.d/netoptions
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.d/netoptions
+++ b/etc/rc.d/netoptions
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.d/network1 b/etc/rc.d/network1
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.d/network1
+++ b/etc/rc.d/network1
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.d/network2 b/etc/rc.d/network2
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.d/network2
+++ b/etc/rc.d/network2
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.d/network3 b/etc/rc.d/network3
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.d/network3
+++ b/etc/rc.d/network3
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.d/routing b/etc/rc.d/routing
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.d/routing
+++ b/etc/rc.d/routing
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rc.network b/etc/rc.network
index ef6c6038b029..c1ffb3735a74 100644
--- a/etc/rc.network
+++ b/etc/rc.network
@@ -514,59 +514,61 @@ network_pass2() {
case ${portmap_enable} in
[Yy][Ee][Ss])
- echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
- ;;
- esac
+ echo -n ' rpcbind'; ${portmap_program:-/usr/sbin/rpcbind} \
+ ${portmap_flags}
- # Start ypserv if we're an NIS server.
- # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
- #
- case ${nis_server_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypserv'; ypserv ${nis_server_flags}
-
- case ${nis_ypxfrd_enable} in
+ # Start ypserv if we're an NIS server.
+ # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server.
+ #
+ case ${nis_server_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.ypxfrd'
- rpc.ypxfrd ${nis_ypxfrd_flags}
+ echo -n ' ypserv'; ypserv ${nis_server_flags}
+
+ case ${nis_ypxfrd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypxfrd'
+ rpc.ypxfrd ${nis_ypxfrd_flags}
+ ;;
+ esac
+
+ case ${nis_yppasswdd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.yppasswdd'
+ rpc.yppasswdd ${nis_yppasswdd_flags}
+ ;;
+ esac
;;
esac
- case ${nis_yppasswdd_enable} in
+ # Start ypbind if we're an NIS client
+ #
+ case ${nis_client_enable} in
[Yy][Ee][Ss])
- echo -n ' rpc.yppasswdd'
- rpc.yppasswdd ${nis_yppasswdd_flags}
+ echo -n ' ypbind'; ypbind ${nis_client_flags}
+ case ${nis_ypset_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' ypset'; ypset ${nis_ypset_flags}
+ ;;
+ esac
;;
esac
- ;;
- esac
- # Start ypbind if we're an NIS client
- #
- case ${nis_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' ypbind'; ypbind ${nis_client_flags}
- case ${nis_ypset_enable} in
+ # Start keyserv if we are running Secure RPC
+ #
+ case ${keyserv_enable} in
[Yy][Ee][Ss])
- echo -n ' ypset'; ypset ${nis_ypset_flags}
+ echo -n ' keyserv'; keyserv ${keyserv_flags}
;;
esac
- ;;
- esac
- # Start keyserv if we are running Secure RPC
- #
- case ${keyserv_enable} in
- [Yy][Ee][Ss])
- echo -n ' keyserv'; keyserv ${keyserv_flags}
- ;;
- esac
-
- # Start ypupdated if we are running Secure RPC and we are NIS master
- #
- case ${rpc_ypupdated_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.ypupdated'; rpc.ypupdated
+ # Start ypupdated if we are running Secure RPC
+ # and we are NIS master
+ #
+ case ${rpc_ypupdated_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.ypupdated'; rpc.ypupdated
+ ;;
+ esac
;;
esac
@@ -582,99 +584,103 @@ network_pass2() {
network_pass3() {
echo -n 'Starting final network daemons:'
- case ${nfs_server_enable} in
+ case ${portmap_enable} in
[Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
-
- case ${weak_mountd_authentication} in
- [Yy][Ee][Ss])
- mountd_flags="${mountd_flags} -n"
- ;;
- esac
+ case ${nfs_server_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="${mountd_flags} -n"
+ ;;
+ esac
- case ${nfs_reserved_port_only} in
- [Yy][Ee][Ss])
- echo -n ' NFS on reserved port only=YES'
- sysctl -w vfs.nfs.nfs_privport=1 >/dev/null
- ;;
- esac
+ mountd ${mountd_flags}
- echo -n ' nfsd'; nfsd ${nfs_server_flags}
+ case ${nfs_reserved_port_only} in
+ [Yy][Ee][Ss])
+ echo -n ' NFS on reserved port only=YES'
+ sysctl -w vfs.nfs.nfs_privport=1 > /dev/null
+ ;;
+ esac
- if [ -n "${nfs_bufpackets}" ]; then
- sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \
- > /dev/null
- fi
+ echo -n ' nfsd'; nfsd ${nfs_server_flags}
- case ${rpc_lockd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.lockd'; rpc.lockd
- ;;
- esac
+ if [ -n "${nfs_bufpackets}" ]; then
+ sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} > /dev/null
+ fi
- case ${rpc_statd_enable} in
- [Yy][Ee][Ss])
- echo -n ' rpc.statd'; rpc.statd
- ;;
- esac
- fi
- ;;
- *)
- case ${single_mountd_enable} in
- [Yy][Ee][Ss])
- if [ -r /etc/exports ]; then
- echo -n ' mountd'
+ case ${rpc_lockd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' rpc.lockd'; rpc.lockd
+ ;;
+ esac
- case ${weak_mountd_authentication} in
+ case ${rpc_statd_enable} in
[Yy][Ee][Ss])
- mountd_flags="-n"
+ echo -n ' rpc.statd'; rpc.statd
;;
esac
+ fi
+ ;;
+ *)
+ case ${single_mountd_enable} in
+ [Yy][Ee][Ss])
+ if [ -r /etc/exports ]; then
+ echo -n ' mountd'
- mountd ${mountd_flags}
+ case ${weak_mountd_authentication} in
+ [Yy][Ee][Ss])
+ mountd_flags="-n"
+ ;;
+ esac
+
+ mountd ${mountd_flags}
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ case ${nfs_client_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
+ if [ -n "${nfs_access_cache}" ]; then
+ echo -n " NFS access cache time=${nfs_access_cache}"
+ sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} >/dev/null
fi
;;
esac
- ;;
- esac
- case ${nfs_client_enable} in
- [Yy][Ee][Ss])
- echo -n ' nfsiod'; nfsiod ${nfs_client_flags}
- if [ -n "${nfs_access_cache}" ]; then
- echo -n " NFS access cache time=${nfs_access_cache}"
- sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \
- >/dev/null
+ # If /var/db/mounttab exists, some nfs-server has not been
+ # sucessfully notified about a previous client shutdown.
+ # If there is no /var/db/mounttab, we do nothing.
+ if [ -f /var/db/mounttab ]; then
+ rpc.umntall -k
fi
- ;;
- esac
- # If /var/db/mounttab exists, some nfs-server has not been
- # sucessfully notified about a previous client shutdown.
- # If there is no /var/db/mounttab, we do nothing.
- if [ -f /var/db/mounttab ]; then
- rpc.umntall -k
- fi
+ case ${amd_enable} in
+ [Yy][Ee][Ss])
+ echo -n ' amd'
+ case ${amd_map_program} in
+ [Nn][Oo] | '')
+ ;;
+ *)
+ amd_flags="${amd_flags} `eval\
+ ${amd_map_program}`"
+ ;;
+ esac
- case ${amd_enable} in
- [Yy][Ee][Ss])
- echo -n ' amd'
- case ${amd_map_program} in
- [Nn][Oo] | '')
- ;;
- *)
- amd_flags="${amd_flags} `eval ${amd_map_program}`"
+ if [ -n "${amd_flags}" ]; then
+ amd -p ${amd_flags}\
+ > /var/run/amd.pid 2> /dev/null
+ else
+ amd 2> /dev/null
+ fi
;;
esac
-
- if [ -n "${amd_flags}" ]; then
- amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null
- else
- amd 2> /dev/null
- fi
;;
esac
diff --git a/etc/rpc b/etc/rpc
index a662bf947066..eab4139e9436 100644
--- a/etc/rpc
+++ b/etc/rpc
@@ -1,8 +1,8 @@
#
# $FreeBSD$
-# rpc 88/08/01 4.0 RPCSRC; from 1.12 88/02/07 SMI
+# rpc 88/08/01 4.0 RPCSRC; from 1.12 99/07/25 SMI
#
-portmapper 100000 portmap sunrpc
+rpcbind 100000 portmap sunrpc rpcbind
rstatd 100001 rstat rstat_svc rup perfmeter
rusersd 100002 rusers
nfs 100003 nfsprog
@@ -29,10 +29,39 @@ status 100024
bootparamd 100026 bootparam
ypupdated 100028 ypupdate
keyserv 100029 keyserver
+sunlink_mapper 100033
tfsd 100037
nsed 100038
nsemntd 100039
-pcnfsd 150001 pcnfs
-amd 300019
+showfhd 100043 showfh
+ioadmd 100055 rpc.ioadmd
+NETlicense 100062
+sunisamd 100065
+debug_svc 100066 dbsrv
cmsd 100068
+bugtraqd 100071
+kerbd 100078
ttdbserver 100083 tooltalk
+event 100101 na.event # SunNet Manager
+logger 100102 na.logger # SunNet Manager
+sync 100104 na.sync
+hostperf 100107 na.hostperf
+activity 100109 na.activity # SunNet Manager
+hostmem 100112 na.hostmem
+sample 100113 na.sample
+x25 100114 na.x25
+ping 100115 na.ping
+rpcnfs 100116 na.rpcnfs
+hostif 100117 na.hostif
+etherif 100118 na.etherif
+iproutes 100120 na.iproutes
+layers 100121 na.layers
+snmp 100122 na.snmp snmp-cmc snmp-synoptics snmp-unisys snmp-utk
+traffic 100123 na.traffic
+nfs_acl 100227
+sadmind 100232
+nisd 100300 rpc.nisd
+nispasswd 100303 rpc.nispasswdd
+ufsd 100233 ufsd
+pcnfsd 150001 pcnfs
+amd 300019
diff --git a/include/Makefile b/include/Makefile
index 1b2ac62bbddc..97788a14bdab 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -7,13 +7,13 @@
# links.
CLEANFILES= osreldate.h version vers.c
-SUBDIR= rpcsvc
+SUBDIR= rpcsvc rpc
FILES= a.out.h ar.h assert.h bitstring.h ctype.h db.h dirent.h disktab.h \
dlfcn.h elf.h err.h fnmatch.h fstab.h \
fts.h glob.h grp.h strhash.h \
hesiod.h histedit.h ieeefp.h ifaddrs.h iso646.h langinfo.h \
libgen.h limits.h link.h locale.h malloc.h memory.h mpool.h \
- ndbm.h netdb.h nl_types.h nlist.h nsswitch.h objformat.h \
+ netconfig.h ndbm.h netdb.h nl_types.h nlist.h nsswitch.h objformat.h \
paths.h pthread.h pthread_np.h pwd.h \
ranlib.h regex.h regexp.h resolv.h rune.h runetype.h \
search.h setjmp.h sgtty.h \
@@ -28,10 +28,6 @@ ARPAFILES= ftp.h inet.h nameser.h nameser_compat.h telnet.h tftp.h
PROTOFILES= dumprestore.h routed.h rwhod.h talkd.h timed.h
-RPCFILES= auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h pmap_rmt.h \
- rpc.h rpc_com.h rpc_msg.h svc.h svc_auth.h types.h xdr.h \
- auth_des.h des.h des_crypt.h
-
MFILES= float.h floatingpoint.h stdarg.h varargs.h
# posix4/aio.h conflicts with dysons and isn't installed:
@@ -86,9 +82,6 @@ beforeinstall: ${SHARED}
cd ${.CURDIR}/protocols; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
${PROTOFILES} ${DESTDIR}/usr/include/protocols
- cd ${.CURDIR}/rpc; \
- ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
- ${RPCFILES} ${DESTDIR}/usr/include/rpc
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
${.OBJDIR}/osreldate.h \
${DESTDIR}/usr/include
diff --git a/include/netconfig.h b/include/netconfig.h
new file mode 100644
index 000000000000..330a5ee281c0
--- /dev/null
+++ b/include/netconfig.h
@@ -0,0 +1,96 @@
+/* $NetBSD: netconfig.h,v 1.1 2000/06/02 22:57:54 fvdl Exp $ */
+/* $FreeBSD$ */
+
+
+#ifndef _NETCONFIG_H_
+#define _NETCONFIG_H_
+
+#include <sys/cdefs.h>
+
+#define NETCONFIG "/etc/netconfig"
+#define NETPATH "NETPATH"
+
+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 */
+ unsigned long nc_nlookups; /* Number of directory lookup libs */
+ char **nc_lookups; /* Names of the libraries */
+ unsigned long nc_unused[9]; /* reserved */
+};
+
+typedef struct {
+ struct netconfig **nc_head;
+ struct netconfig **nc_curr;
+} NCONF_HANDLE;
+
+/*
+ * nc_semantics values
+ */
+#define NC_TPI_CLTS 1
+#define NC_TPI_COTS 2
+#define NC_TPI_COTS_ORD 3
+#define NC_TPI_RAW 4
+
+/*
+ * nc_flag values
+ */
+#define NC_NOFLAG 0x00
+#define NC_VISIBLE 0x01
+#define NC_BROADCAST 0x02
+
+/*
+ * nc_protofmly values
+ */
+#define NC_NOPROTOFMLY "-"
+#define NC_LOOPBACK "loopback"
+#define NC_INET "inet"
+#define NC_INET6 "inet6"
+#define NC_IMPLINK "implink"
+#define NC_PUP "pup"
+#define NC_CHAOS "chaos"
+#define NC_NS "ns"
+#define NC_NBS "nbs"
+#define NC_ECMA "ecma"
+#define NC_DATAKIT "datakit"
+#define NC_CCITT "ccitt"
+#define NC_SNA "sna"
+#define NC_DECNET "decnet"
+#define NC_DLI "dli"
+#define NC_LAT "lat"
+#define NC_HYLINK "hylink"
+#define NC_APPLETALK "appletalk"
+#define NC_NIT "nit"
+#define NC_IEEE802 "ieee802"
+#define NC_OSI "osi"
+#define NC_X25 "x25"
+#define NC_OSINET "osinet"
+#define NC_GOSIP "gosip"
+
+/*
+ * nc_proto values
+ */
+#define NC_NOPROTO "-"
+#define NC_TCP "tcp"
+#define NC_UDP "udp"
+#define NC_ICMP "icmp"
+
+__BEGIN_DECLS
+void *setnetconfig __P((void));
+struct netconfig *getnetconfig __P((void *));
+struct netconfig *getnetconfigent __P((char *));
+void freenetconfigent __P((struct netconfig *));
+int endnetconfig __P((void *));
+
+void *setnetpath __P((void));
+struct netconfig *getnetpath __P((void *));
+int endnetpath(void *);
+
+void nc_perror __P((const char *));
+char *nc_sperror __P((void));
+__END_DECLS
+
+#endif /* _NETCONFIG_H_ */
diff --git a/include/pthread_np.h b/include/pthread_np.h
index 485048bee30c..f5ac7f5aeb7c 100644
--- a/include/pthread_np.h
+++ b/include/pthread_np.h
@@ -29,6 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $FreeBSD$
*/
#ifndef _PTHREAD_NP_H_
#define _PTHREAD_NP_H_
@@ -52,6 +53,7 @@ int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *, int));
void pthread_set_name_np __P((pthread_t, char *));
int pthread_switch_add_np __P((pthread_switch_routine_t));
int pthread_switch_delete_np __P((pthread_switch_routine_t));
+int pthread_main_np __P((void));
__END_DECLS
#endif
diff --git a/include/rpc/Makefile b/include/rpc/Makefile
new file mode 100644
index 000000000000..1d159746eda4
--- /dev/null
+++ b/include/rpc/Makefile
@@ -0,0 +1,37 @@
+# from: @(#)Makefile 2.3 88/08/11 4.0 RPCSRC
+# $FreeBSD$
+
+.SUFFIXES: .x
+
+RPCCOM = rpcgen -C
+
+HDRS= rpcb_prot.h
+
+XFILES= rpcb_prot.x
+
+HFILES= auth.h auth_unix.h clnt.h clnt_soc.h clnt_stat.h \
+ nettype.h pmap_clnt.h pmap_prot.h pmap_rmt.h raw.h \
+ rpc.h rpc_msg.h rpcb_clnt.h rpcent.h rpc_com.h \
+ svc.h svc_auth.h svc_soc.h svc_dg.h types.h xdr.h
+
+# Secure RPC
+HFILES+= auth_des.h des.h des_crypt.h
+
+# Kerberos
+HFILES+= auth_kerb.h
+
+CLEANFILES+= ${HDRS}
+
+all: ${HDRS}
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${HFILES:S;^;${.CURDIR}/;} \
+ ${XFILES:S;^;${.CURDIR}/;} \
+ ${HDRS} \
+ ${DESTDIR}/usr/include/rpc
+
+.x.h:
+ ${RPCCOM} -h -DWANT_NFS3 ${.IMPSRC} -o ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/include/rpc/auth.h b/include/rpc/auth.h
index 4d6c38dbac17..68e8827b910c 100644
--- a/include/rpc/auth.h
+++ b/include/rpc/auth.h
@@ -1,3 +1,5 @@
+/* $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -28,6 +30,7 @@
*
* from: @(#)auth.h 1.17 88/02/08 SMI
* from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
+ * from: @(#)auth.h 1.43 98/02/02 SMI
* $FreeBSD$
*/
@@ -43,6 +46,8 @@
#ifndef _RPC_AUTH_H
#define _RPC_AUTH_H
+#include <rpc/xdr.h>
+#include <rpc/clnt_stat.h>
#include <sys/cdefs.h>
#include <sys/socket.h>
@@ -50,6 +55,67 @@
#define MAXNETNAMELEN 255 /* maximum length of network user's name */
/*
+ * Client side authentication/security data
+ */
+
+typedef struct sec_data {
+ u_int secmod; /* security mode number e.g. in nfssec.conf */
+ u_int rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */
+ int flags; /* AUTH_F_xxx flags */
+ caddr_t data; /* opaque data per flavor */
+} sec_data_t;
+
+#ifdef _SYSCALL32_IMPL
+struct sec_data32 {
+ uint32_t secmod; /* security mode number e.g. in nfssec.conf */
+ uint32_t rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */
+ int32_t flags; /* AUTH_F_xxx flags */
+ caddr32_t data; /* opaque data per flavor */
+};
+#endif /* _SYSCALL32_IMPL */
+
+/*
+ * AUTH_DES flavor specific data from sec_data opaque data field.
+ * AUTH_KERB has the same structure.
+ */
+typedef struct des_clnt_data {
+ struct netbuf syncaddr; /* time sync addr */
+ struct knetconfig *knconf; /* knetconfig info that associated */
+ /* with the syncaddr. */
+ char *netname; /* server's netname */
+ int netnamelen; /* server's netname len */
+} dh_k4_clntdata_t;
+
+#ifdef _SYSCALL32_IMPL
+struct des_clnt_data32 {
+ struct netbuf32 syncaddr; /* time sync addr */
+ caddr32_t knconf; /* knetconfig info that associated */
+ /* with the syncaddr. */
+ caddr32_t netname; /* server's netname */
+ int32_t netnamelen; /* server's netname len */
+};
+#endif /* _SYSCALL32_IMPL */
+
+#ifdef KERBEROS
+/*
+ * flavor specific data to hold the data for AUTH_DES/AUTH_KERB(v4)
+ * in sec_data->data opaque field.
+ */
+typedef struct krb4_svc_data {
+ int window; /* window option value */
+} krb4_svcdata_t;
+
+typedef struct krb4_svc_data des_svcdata_t;
+#endif /* KERBEROS */
+
+/*
+ * authentication/security specific flags
+ */
+#define AUTH_F_RPCTIMESYNC 0x001 /* use RPC to do time sync */
+#define AUTH_F_TRYNONE 0x002 /* allow fall back to AUTH_NONE */
+
+
+/*
* Status returned from authentication check
*/
enum auth_stat {
@@ -67,18 +133,32 @@ enum auth_stat {
*/
AUTH_INVALIDRESP=6, /* bogus response verifier */
AUTH_FAILED=7 /* some unknown reason */
+#ifdef KERBEROS
+ /*
+ * kerberos errors
+ */
+ AUTH_KERB_GENERIC = 8, /* kerberos generic error */
+ AUTH_TIMEEXPIRE = 9, /* time of credential expired */
+ AUTH_TKT_FILE = 10, /* something wrong with ticket file */
+ AUTH_DECODE = 11, /* can't decode authenticator */
+ AUTH_NET_ADDR = 12 /* wrong net address in ticket */
+#endif /* KERBEROS */
};
union des_block {
struct {
- u_int32_t high;
- u_int32_t low;
+ uint32_t high;
+ uint32_t low;
} key;
char c[8];
};
typedef union des_block des_block;
__BEGIN_DECLS
-extern bool_t xdr_des_block __P((XDR *, des_block *));
+#ifdef __STDC__
+extern bool_t xdr_des_block(XDR *, des_block *);
+#else
+extern bool_t xdr_des_block();
+#endif
__END_DECLS
/*
@@ -89,29 +169,26 @@ struct opaque_auth {
caddr_t oa_base; /* address of more auth stuff */
u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
};
-__BEGIN_DECLS
-bool_t xdr_opaque_auth __P((XDR *xdrs, struct opaque_auth *ap));
-__END_DECLS
/*
* Auth handle, interface to client side authenticators.
*/
-typedef struct __rpc_auth {
+typedef struct __auth {
struct opaque_auth ah_cred;
struct opaque_auth ah_verf;
union des_block ah_key;
struct auth_ops {
- void (*ah_nextverf) __P((struct __rpc_auth *));
+ void (*ah_nextverf) (struct __auth *);
/* nextverf & serialize */
- int (*ah_marshal) __P((struct __rpc_auth *, XDR *));
+ int (*ah_marshal) (struct __auth *, XDR *);
/* validate verifier */
- int (*ah_validate) __P((struct __rpc_auth *,
- struct opaque_auth *));
+ int (*ah_validate) (struct __auth *,
+ struct opaque_auth *);
/* refresh credentials */
- int (*ah_refresh) __P((struct __rpc_auth *));
+ int (*ah_refresh) (struct __auth *, void *);
/* destroy this structure */
- void (*ah_destroy) __P((struct __rpc_auth *));
+ void (*ah_destroy) (struct __auth *);
} *ah_ops;
caddr_t ah_private;
} AUTH;
@@ -140,10 +217,10 @@ typedef struct __rpc_auth {
#define auth_validate(auth, verfp) \
((*((auth)->ah_ops->ah_validate))((auth), verfp))
-#define AUTH_REFRESH(auth) \
- ((*((auth)->ah_ops->ah_refresh))(auth))
-#define auth_refresh(auth) \
- ((*((auth)->ah_ops->ah_refresh))(auth))
+#define AUTH_REFRESH(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
#define AUTH_DESTROY(auth) \
((*((auth)->ah_ops->ah_destroy))(auth))
@@ -151,14 +228,16 @@ typedef struct __rpc_auth {
((*((auth)->ah_ops->ah_destroy))(auth))
+__BEGIN_DECLS
extern struct opaque_auth _null_auth;
+__END_DECLS
/*
* These are the various implementations of client side authenticators.
*/
/*
- * Unix style authentication
+ * System style authentication
* AUTH *authunix_create(machname, uid, gid, len, aup_gids)
* char *machname;
* int uid;
@@ -167,94 +246,105 @@ extern struct opaque_auth _null_auth;
* int *aup_gids;
*/
__BEGIN_DECLS
-struct sockaddr_in;
-extern AUTH *authunix_create __P((char *, int, int, int, int *));
-extern AUTH *authunix_create_default __P((void));
-extern AUTH *authnone_create __P((void));
+extern AUTH *authunix_create(char *, int, int, int,
+ int *);
+extern AUTH *authunix_create_default(void); /* takes no parameters */
+extern AUTH *authnone_create(void); /* takes no parameters */
__END_DECLS
-
-/* Forward compatibility with TI-RPC */
-#define authsys_create authunix_create
-#define authsys_create_default authunix_create_default
-
/*
* DES style authentication
- * AUTH *authdes_create(servername, window, timehost, ckey)
+ * AUTH *authsecdes_create(servername, window, timehost, ckey)
* char *servername; - network name of server
* u_int window; - time to live
- * struct sockaddr *timehost; - optional hostname to sync with
+ * const char *timehost; - optional hostname to sync with
* des_block *ckey; - optional conversation key to use
*/
__BEGIN_DECLS
-extern AUTH *authdes_create __P(( char *, u_int, struct sockaddr *, des_block * ));
-#ifdef NOTYET
-/*
- * TI-RPC supports this call, but it requires the inclusion of
- * NIS+-specific headers which would require the inclusion of other
- * headers which would result in a tangled mess. For now, the NIS+
- * code prototypes this routine internally.
- */
-extern AUTH *authdes_pk_create __P(( char *, netobj *, u_int,
- struct sockaddr *, des_block *,
- nis_server * ));
-#endif
+extern AUTH *authdes_create (char *, u_int, struct sockaddr *, des_block *);
+extern AUTH *authdes_seccreate (const char *, const u_int, const char *,
+ const des_block *);
+__END_DECLS
+
+__BEGIN_DECLS
+extern bool_t xdr_opaque_auth __P((XDR *, struct opaque_auth *));
__END_DECLS
+#define authsys_create(c,i1,i2,i3,ip) authunix_create((c),(i1),(i2),(i3),(ip))
+#define authsys_create_default() authunix_create_default()
+
/*
* Netname manipulation routines.
*/
__BEGIN_DECLS
-extern int netname2user __P(( char *, uid_t *, gid_t *, int *, gid_t *));
-extern int netname2host __P(( char *, char *, int ));
-extern int getnetname __P(( char * ));
-extern int user2netname __P(( char *, uid_t, char * ));
-extern int host2netname __P(( char *, char *, char * ));
-extern void passwd2des __P(( char *, char * ));
+extern int getnetname(char *);
+extern int host2netname(char *, const char *, const char *);
+extern int user2netname(char *, const uid_t, const char *);
+extern int netname2user(char *, uid_t *, gid_t *, int *, gid_t *);
+extern int netname2host(char *, char *, const int);
+extern void passwd2des ( char *, char * );
__END_DECLS
/*
- * Keyserv interface routines.
- * XXX Should not be here.
+ *
+ * These routines interface to the keyserv daemon
+ *
*/
-#ifndef HEXKEYBYTES
-#define HEXKEYBYTES 48
-#endif
-typedef char kbuf[HEXKEYBYTES];
-typedef char *namestr;
-
-struct netstarg {
- kbuf st_priv_key;
- kbuf st_pub_key;
- namestr st_netname;
-};
+__BEGIN_DECLS
+extern int key_decryptsession(const char *, des_block *);
+extern int key_encryptsession(const char *, des_block *);
+extern int key_gendes(des_block *);
+extern int key_setsecret(const char *);
+extern int key_secretkey_is_set(void);
+__END_DECLS
+#ifdef KERBEROS
+/*
+ * Kerberos style authentication
+ * AUTH *authkerb_seccreate(service, srv_inst, realm, window, timehost, status)
+ * const char *service; - service name
+ * const char *srv_inst; - server instance
+ * const char *realm; - server realm
+ * const u_int window; - time to live
+ * const char *timehost; - optional hostname to sync with
+ * int *status; - kerberos status returned
+ */
__BEGIN_DECLS
-extern int key_decryptsession __P(( const char *, des_block * ));
-extern int key_decryptsession_pk __P(( char *, netobj *, des_block * ));
-extern int key_encryptsession __P(( const char *, des_block * ));
-extern int key_encryptsession_pk __P(( char *, netobj *, des_block * ));
-extern int key_gendes __P(( des_block * ));
-extern int key_setsecret __P(( const char * ));
-extern int key_secretkey_is_set __P(( void ));
-extern int key_setnet __P(( struct netstarg * ));
-extern int key_get_conv __P(( char *, des_block * ));
+extern AUTH *authkerb_seccreate(const char *, const char *, const char *,
+ const u_int, const char *, int *);
__END_DECLS
/*
- * Publickey routines.
+ * Map a kerberos credential into a unix cred.
+ *
+ * authkerb_getucred(rqst, uid, gid, grouplen, groups)
+ * const struct svc_req *rqst; - request pointer
+ * uid_t *uid;
+ * gid_t *gid;
+ * short *grouplen;
+ * int *groups;
+ *
*/
__BEGIN_DECLS
-extern int getpublickey __P(( char *, char * ));
-extern int getpublicandprivatekey __P(( char *, char * ));
-extern int getsecretkey __P(( char *, char *, char * ));
+extern int authkerb_getucred(/* struct svc_req *, uid_t *, gid_t *,
+ short *, int * */);
__END_DECLS
+#endif /* KERBEROS */
+__BEGIN_DECLS
+struct svc_req;
+struct rpc_msg;
+enum auth_stat _svcauth_null __P((struct svc_req *, struct rpc_msg *));
+enum auth_stat _svcauth_short __P((struct svc_req *, struct rpc_msg *));
+enum auth_stat _svcauth_unix __P((struct svc_req *, struct rpc_msg *));
+__END_DECLS
#define AUTH_NONE 0 /* no authentication */
#define AUTH_NULL 0 /* backward compatibility */
-#define AUTH_UNIX 1 /* unix style (uid, gids) */
-#define AUTH_SYS 1 /* forward compatibility */
+#define AUTH_SYS 1 /* unix style (uid, gids) */
+#define AUTH_UNIX AUTH_SYS
#define AUTH_SHORT 2 /* short hand unix style */
-#define AUTH_DES 3 /* des style (encrypted timestamps) */
+#define AUTH_DH 3 /* for Diffie-Hellman mechanism */
+#define AUTH_DES AUTH_DH /* for backward compatibility */
+#define AUTH_KERB 4 /* kerberos style */
#endif /* !_RPC_AUTH_H */
diff --git a/include/rpc/auth_des.h b/include/rpc/auth_des.h
index a7635f87e17c..964e77480da7 100644
--- a/include/rpc/auth_des.h
+++ b/include/rpc/auth_des.h
@@ -1,4 +1,5 @@
/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */
+/* $FreeBSD$ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,10 +27,13 @@
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
+ *
+ * from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC
+ * from: @(#)auth_des.h 1.14 94/04/25 SMI
*/
/*
- * Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/*
@@ -102,8 +106,21 @@ struct authdes_verf {
#define adv_xtimeverf adv_time_u.adv_xtime
#define adv_nickname adv_int_u
+/*
+ * Map a des credential into a unix cred.
+ *
+ */
__BEGIN_DECLS
extern int authdes_getucred __P(( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * ));
__END_DECLS
+__BEGIN_DECLS
+extern bool_t xdr_authdes_cred(XDR *, struct authdes_cred *);
+extern bool_t xdr_authdes_verf(XDR *, struct authdes_verf *);
+extern int rtime(dev_t, struct netbuf *, int, struct timeval *,
+ struct timeval *);
+extern void kgetnetname(char *);
+extern enum auth_stat _svcauth_des(struct svc_req *, struct rpc_msg *);
+__END_DECLS
+
#endif /* ndef _AUTH_DES_ */
diff --git a/include/rpc/auth_kerb.h b/include/rpc/auth_kerb.h
new file mode 100644
index 000000000000..f0145bd4789d
--- /dev/null
+++ b/include/rpc/auth_kerb.h
@@ -0,0 +1,143 @@
+/* $FreeBSD$ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * auth_kerb.h, Protocol for Kerberos style authentication for RPC
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_AUTH_KERB_H
+#define _RPC_AUTH_KERB_H
+
+#ifdef KERBEROS
+
+#pragma ident "@(#)auth_kerb.h 1.10 94/04/25 SMI"
+
+#include <kerberos/krb.h>
+#include <sys/socket.h>
+#include <sys/t_kuser.h>
+#include <netinet/in.h>
+#include <rpc/svc.h>
+
+/*
+ * There are two kinds of "names": fullnames and nicknames
+ */
+enum authkerb_namekind {
+ AKN_FULLNAME,
+ AKN_NICKNAME
+};
+/*
+ * A fullname contains the ticket and the window
+ */
+struct authkerb_fullname {
+ KTEXT_ST ticket;
+ u_long window; /* associated window */
+};
+
+/*
+ * cooked credential stored in rq_clntcred
+ */
+struct authkerb_clnt_cred {
+ /* start of AUTH_DAT */
+ unsigned char k_flags; /* Flags from ticket */
+ char pname[ANAME_SZ]; /* Principal's name */
+ char pinst[INST_SZ]; /* His Instance */
+ char prealm[REALM_SZ]; /* His Realm */
+ unsigned long checksum; /* Data checksum (opt) */
+ C_Block session; /* Session Key */
+ int life; /* Life of ticket */
+ unsigned long time_sec; /* Time ticket issued */
+ unsigned long address; /* Address in ticket */
+ /* KTEXT_ST reply; Auth reply (opt) */
+ /* end of AUTH_DAT */
+ unsigned long expiry; /* time the ticket is expiring */
+ u_long nickname; /* Nickname into cache */
+ u_long window; /* associated window */
+};
+
+typedef struct authkerb_clnt_cred authkerb_clnt_cred;
+
+/*
+ * A credential
+ */
+struct authkerb_cred {
+ enum authkerb_namekind akc_namekind;
+ struct authkerb_fullname akc_fullname;
+ u_long akc_nickname;
+};
+
+/*
+ * A kerb authentication verifier
+ */
+struct authkerb_verf {
+ union {
+ struct timeval akv_ctime; /* clear time */
+ des_block akv_xtime; /* crypt time */
+ } akv_time_u;
+ u_long akv_int_u;
+};
+
+/*
+ * des authentication verifier: client variety
+ *
+ * akv_timestamp is the current time.
+ * akv_winverf is the credential window + 1.
+ * Both are encrypted using the conversation key.
+ */
+#ifndef akv_timestamp
+#define akv_timestamp akv_time_u.akv_ctime
+#define akv_xtimestamp akv_time_u.akv_xtime
+#define akv_winverf akv_int_u
+#endif
+/*
+ * des authentication verifier: server variety
+ *
+ * akv_timeverf is the client's timestamp + client's window
+ * akv_nickname is the server's nickname for the client.
+ * akv_timeverf is encrypted using the conversation key.
+ */
+#ifndef akv_timeverf
+#define akv_timeverf akv_time_u.akv_ctime
+#define akv_xtimeverf akv_time_u.akv_xtime
+#define akv_nickname akv_int_u
+#endif
+
+/*
+ * Register the service name, instance and realm.
+ */
+extern int authkerb_create(char *, char *, char *, u_int,
+ struct netbuf *, int *, dev_t, int, AUTH **);
+extern bool_t xdr_authkerb_cred(XDR *, struct authkerb_cred *);
+extern bool_t xdr_authkerb_verf(XDR *, struct authkerb_verf *);
+extern int svc_kerb_reg(SVCXPRT *, char *, char *, char *);
+extern enum auth_stat _svcauth_kerb(struct svc_req *, struct rpc_msg *);
+
+#endif KERBEROS
+#endif /* !_RPC_AUTH_KERB_H */
diff --git a/include/rpc/clnt.h b/include/rpc/clnt.h
index cf2116d611fa..2b0587b169ef 100644
--- a/include/rpc/clnt.h
+++ b/include/rpc/clnt.h
@@ -1,3 +1,5 @@
+/* $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,7 +28,7 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*
- * from: @(#)clnt.h 1.31 88/02/08 SMI
+ * from: @(#)clnt.h 1.31 94/04/29 SMI
* from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
*/
@@ -39,52 +41,28 @@
#ifndef _RPC_CLNT_H_
#define _RPC_CLNT_H_
+#include <rpc/clnt_stat.h>
#include <sys/cdefs.h>
+#include <netconfig.h>
#include <sys/un.h>
/*
- * Rpc calls return an enum clnt_stat. This should be looked at more,
- * since each implementation is required to live with this (implementation
- * independent) list of errors.
- */
-enum clnt_stat {
- RPC_SUCCESS=0, /* call succeeded */
- /*
- * local errors
- */
- RPC_CANTENCODEARGS=1, /* can't encode arguments */
- RPC_CANTDECODERES=2, /* can't decode results */
- RPC_CANTSEND=3, /* failure in sending call */
- RPC_CANTRECV=4, /* failure in receiving result */
- RPC_TIMEDOUT=5, /* call timed out */
- /*
- * remote errors
- */
- RPC_VERSMISMATCH=6, /* rpc versions not compatible */
- RPC_AUTHERROR=7, /* authentication error */
- RPC_PROGUNAVAIL=8, /* program not available */
- RPC_PROGVERSMISMATCH=9, /* program version mismatched */
- RPC_PROCUNAVAIL=10, /* procedure unavailable */
- RPC_CANTDECODEARGS=11, /* decode arguments error */
- RPC_SYSTEMERROR=12, /* generic "other problem" */
-
- /*
- * callrpc & clnt_create errors
- */
- RPC_UNKNOWNHOST=13, /* unknown host name */
- RPC_UNKNOWNPROTO=17, /* unkown protocol */
-
- /*
- * _ create errors
- */
- RPC_PMAPFAILURE=14, /* the pmapper failed in its call */
- RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
- /*
- * unspecified error
- */
- RPC_FAILED=16
-};
+ * Well-known IPV6 RPC broadcast address.
+ */
+#define RPCB_MULTICAST_ADDR "ff02::202"
+/*
+ * the following errors are in general unrecoverable. The caller
+ * should give up rather than retry.
+ */
+#define IS_UNRECOVERABLE_RPC(s) (((s) == RPC_AUTHERROR) || \
+ ((s) == RPC_CANTENCODEARGS) || \
+ ((s) == RPC_CANTDECODERES) || \
+ ((s) == RPC_VERSMISMATCH) || \
+ ((s) == RPC_PROCUNAVAIL) || \
+ ((s) == RPC_PROGUNAVAIL) || \
+ ((s) == RPC_PROGVERSMISMATCH) || \
+ ((s) == RPC_CANTDECODEARGS))
/*
* Error info.
@@ -95,8 +73,8 @@ struct rpc_err {
int RE_errno; /* related system error */
enum auth_stat RE_why; /* why the auth error occurred */
struct {
- u_int32_t low; /* lowest verion supported */
- u_int32_t high; /* highest verion supported */
+ rpcvers_t low; /* lowest version supported */
+ rpcvers_t high; /* highest version supported */
} RE_vers;
struct { /* maybe meaningful if RPC_FAILED */
int32_t s1;
@@ -112,7 +90,7 @@ struct rpc_err {
/*
* Client rpc handle.
- * Created by individual implementations, see e.g. rpc_udp.c.
+ * Created by individual implementations
* Client is responsible for initializing auth, see e.g. auth_none.c.
*/
typedef struct __rpc_client {
@@ -120,7 +98,7 @@ typedef struct __rpc_client {
struct clnt_ops {
/* call remote procedure */
enum clnt_stat (*cl_call) __P((struct __rpc_client *,
- u_long, xdrproc_t, caddr_t, xdrproc_t,
+ rpcproc_t, xdrproc_t, caddr_t, xdrproc_t,
caddr_t, struct timeval));
/* abort a call */
void (*cl_abort) __P((struct __rpc_client *));
@@ -134,13 +112,37 @@ typedef struct __rpc_client {
void (*cl_destroy) __P((struct __rpc_client *));
/* the ioctl() of rpc */
bool_t (*cl_control) __P((struct __rpc_client *, u_int,
- void *));
+ char *));
} *cl_ops;
- caddr_t cl_private; /* private stuff */
+ void *cl_private; /* private stuff */
+ char *cl_netid; /* network token */
+ char *cl_tp; /* device name */
} CLIENT;
/*
+ * Timers used for the pseudo-transport protocol when using datagrams
+ */
+struct rpc_timers {
+ u_short rt_srtt; /* smoothed round-trip time */
+ u_short rt_deviate; /* estimated deviation */
+ u_long rt_rtxcur; /* current (backed-off) rto */
+};
+
+/*
+ * Feedback values used for possible congestion and rate control
+ */
+#define FEEDBACK_REXMIT1 1 /* first retransmit */
+#define FEEDBACK_OK 2 /* no retransmits */
+
+/* Used to set version of portmapper used in broadcast */
+
+#define CLCR_SET_LOWVERS 3
+#define CLCR_GET_LOWVERS 4
+
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+/*
* client side rpc interface ops
*
* Parameter types are:
@@ -151,19 +153,19 @@ typedef struct __rpc_client {
* enum clnt_stat
* CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
* CLIENT *rh;
- * u_long proc;
+ * rpcproc_t proc;
* xdrproc_t xargs;
* caddr_t argsp;
* xdrproc_t xres;
* caddr_t resp;
* struct timeval timeout;
*/
-#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
- ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \
- xres, (caddr_t)resp, secs))
-#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
- ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \
- xres, (caddr_t)resp, secs))
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, \
+ (caddr_t)(void *)argsp, xres, (caddr_t)(void *)resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, \
+ (caddr_t)(void *)argsp, xres, (caddr_t)(void *)resp, secs))
/*
* void
@@ -203,43 +205,31 @@ typedef struct __rpc_client {
#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
/*
- * control operations that apply to udp, tcp and unix transports
- *
- * Note: options marked XXX are no-ops in this implementation of RPC.
- * The are present in TI-RPC but can't be implemented here since they
- * depend on the presence of STREAMS/TLI, which we don't have.
- *
+ * control operations that apply to both udp and tcp transports
*/
-#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
-#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
-#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
-#define CLGET_FD 6 /* get connections file descriptor */
-#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */
-#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */
-#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy */
-#define CLGET_XID 10 /* Get xid */
-#define CLSET_XID 11 /* Set xid */
-#define CLGET_VERS 12 /* Get version number */
-#define CLSET_VERS 13 /* Set version number */
-#define CLGET_PROG 14 /* Get program number */
-#define CLSET_PROG 15 /* Set program number */
-#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */
-#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */
-#define CLSET_POP_TIMOD 18 /* pop timod XXX */
-
-/*
- * udp only control operations
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+#define CLGET_FD 6 /* get connections file descriptor */
+#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) */
+#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */
+#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy */
+#define CLGET_XID 10 /* Get xid */
+#define CLSET_XID 11 /* Set xid */
+#define CLGET_VERS 12 /* Get version number */
+#define CLSET_VERS 13 /* Set version number */
+#define CLGET_PROG 14 /* Get program number */
+#define CLSET_PROG 15 /* Set program number */
+#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) */
+#define CLSET_PUSH_TIMOD 17 /* push timod if not already present */
+#define CLSET_POP_TIMOD 18 /* pop timod */
+/*
+ * Connectionless only control operations
*/
#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
/*
- * Operations which GSSAPI needs. (Bletch.)
- */
-#define CLGET_LOCAL_ADDR 19 /* get local addr (sockaddr) */
-
-
-/*
* void
* CLNT_DESTROY(rh);
* CLIENT *rh;
@@ -254,16 +244,16 @@ typedef struct __rpc_client {
* and network administration.
*/
-#define RPCTEST_PROGRAM ((u_long)1)
-#define RPCTEST_VERSION ((u_long)1)
-#define RPCTEST_NULL_PROC ((u_long)2)
-#define RPCTEST_NULL_BATCH_PROC ((u_long)3)
+#define RPCTEST_PROGRAM ((rpcprog_t)1)
+#define RPCTEST_VERSION ((rpcvers_t)1)
+#define RPCTEST_NULL_PROC ((rpcproc_t)2)
+#define RPCTEST_NULL_BATCH_PROC ((rpcproc_t)3)
/*
* By convention, procedure 0 takes null arguments and returns them
*/
-#define NULLPROC ((u_long)0)
+#define NULLPROC ((rpcproc_t)0)
/*
* Below are the client handle creation routines for the various
@@ -272,108 +262,112 @@ typedef struct __rpc_client {
*/
/*
- * Memory based rpc (for speed check and testing)
+ * Generic client creation routine. Supported protocols are those that
+ * belong to the nettype namespace (/etc/netconfig).
* CLIENT *
- * clntraw_create(prog, vers)
- * u_long prog;
- * u_long vers;
+ * clnt_create(host, prog, vers, prot);
+ * const char *host; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const char *prot; -- protocol
*/
__BEGIN_DECLS
-extern CLIENT *clntraw_create __P((u_long, u_long));
-__END_DECLS
-
+extern CLIENT *clnt_create __P((const char *, const rpcprog_t, const rpcvers_t,
+ const char *));
+/*
+ *
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const char *nettype; -- network type
+ */
/*
- * Generic client creation routine. Supported protocols are "udp", "tcp"
- * and "unix".
- * CLIENT *
- * clnt_create(host, prog, vers, prot);
- * char *host; -- hostname
- * u_long prog; -- program number
- * u_long vers; -- version number
- * char *prot; -- protocol
+ * Generic client creation routine. Supported protocols are which belong
+ * to the nettype name space.
+ */
+extern CLIENT *clnt_create_vers __P((const char *, const rpcprog_t, rpcvers_t *,
+ const rpcvers_t, const rpcvers_t,
+ const char *));
+/*
+ * const char *host; -- hostname
+ * const rpcprog_t prog; -- program number
+ * rpcvers_t *vers_out; -- servers highest available version
+ * const rpcvers_t vers_low; -- low version number
+ * const rpcvers_t vers_high; -- high version number
+ * const char *nettype; -- network type
*/
-__BEGIN_DECLS
-extern CLIENT *clnt_create __P((char *, u_long, u_long, char *));
-__END_DECLS
/*
- * TCP based rpc
- * CLIENT *
- * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
- * struct sockaddr_in *raddr;
- * u_long prog;
- * u_long version;
- * register int *sockp;
- * u_int sendsz;
- * u_int recvsz;
+ * Generic client creation routine. It takes a netconfig structure
+ * instead of nettype
+ */
+extern CLIENT *clnt_tp_create __P((const char *, const rpcprog_t,
+ const rpcvers_t, const struct netconfig *));
+/*
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const struct netconfig *netconf; -- network config structure
*/
-__BEGIN_DECLS
-extern CLIENT *clnttcp_create __P((struct sockaddr_in *,
- u_long,
- u_long,
- int *,
- u_int,
- u_int));
-__END_DECLS
+/*
+ * Generic TLI create routine. Only provided for compatibility.
+ */
+extern CLIENT *clnt_tli_create __P((const int, const struct netconfig *,
+ const struct netbuf *, const rpcprog_t,
+ const rpcvers_t, const u_int, const u_int));
/*
- * UDP based rpc.
- * CLIENT *
- * clntudp_create(raddr, program, version, wait, sockp)
- * struct sockaddr_in *raddr;
- * u_long program;
- * u_long version;
- * struct timeval wait;
- * int *sockp;
- *
- * Same as above, but you specify max packet sizes.
- * CLIENT *
- * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
- * struct sockaddr_in *raddr;
- * u_long program;
- * u_long version;
- * struct timeval wait;
- * int *sockp;
- * u_int sendsz;
- * u_int recvsz;
+ * const register int fd; -- fd
+ * const struct netconfig *nconf; -- netconfig structure
+ * const struct netbuf *svcaddr; -- servers address
+ * const u_long prog; -- program number
+ * const u_long vers; -- version number
+ * const u_int sendsz; -- send size
+ * const u_int recvsz; -- recv size
*/
-__BEGIN_DECLS
-extern CLIENT *clntudp_create __P((struct sockaddr_in *,
- u_long,
- u_long,
- struct timeval,
- int *));
-extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *,
- u_long,
- u_long,
- struct timeval,
- int *,
- u_int,
- u_int));
-__END_DECLS
+/*
+ * Low level clnt create routine for connectionful transports, e.g. tcp.
+ */
+extern CLIENT *clnt_vc_create __P((const int, const struct netbuf *,
+ const rpcprog_t, const rpcvers_t,
+ const u_int, const u_int));
+/*
+ * const int fd; -- open file descriptor
+ * const struct netbuf *svcaddr; -- servers address
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const u_int sendsz; -- buffer recv size
+ * const u_int recvsz; -- buffer send size
+ */
/*
- * AF_UNIX based rpc
+ * Low level clnt create routine for connectionless transports, e.g. udp.
+ */
+extern CLIENT *clnt_dg_create __P((const int, const struct netbuf *,
+ const rpcprog_t, const rpcvers_t,
+ const u_int, const u_int));
+/*
+ * const int fd; -- open file descriptor
+ * const struct netbuf *svcaddr; -- servers address
+ * const rpcprog_t program; -- program number
+ * const rpcvers_t version; -- version number
+ * const u_int sendsz; -- buffer recv size
+ * const u_int recvsz; -- buffer send size
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
* CLIENT *
- * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
- * struct sockaddr_un *raddr;
+ * clnt_raw_create(prog, vers)
* u_long prog;
- * u_long version;
- * register int *sockp;
- * u_int sendsz;
- * u_int recvsz;
+ * u_long vers;
*/
-__BEGIN_DECLS
-extern CLIENT *clntunix_create __P((struct sockaddr_un *,
- u_long,
- u_long,
- int *,
- u_int,
- u_int));
+extern CLIENT *clnt_raw_create __P((rpcprog_t, rpcvers_t));
+
__END_DECLS
@@ -381,8 +375,8 @@ __END_DECLS
* Print why creation failed
*/
__BEGIN_DECLS
-extern void clnt_pcreateerror __P((char *)); /* stderr */
-extern char *clnt_spcreateerror __P((char *)); /* string */
+extern void clnt_pcreateerror __P((const char *)); /* stderr */
+extern char *clnt_spcreateerror __P((const char *)); /* string */
__END_DECLS
/*
@@ -397,8 +391,8 @@ __END_DECLS
* Print an English error message, given the client error code
*/
__BEGIN_DECLS
-extern void clnt_perror __P((CLIENT *, char *)); /* stderr */
-extern char *clnt_sperror __P((CLIENT *, char *)); /* string */
+extern void clnt_perror __P((CLIENT *, const char *)); /* stderr */
+extern char *clnt_sperror __P((CLIENT *, const char *)); /* string */
__END_DECLS
@@ -410,10 +404,94 @@ struct rpc_createerr {
struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
};
+#ifdef _THREAD_SAFE
+__BEGIN_DECLS
+extern struct rpc_createerr *__rpc_createerr __P((void));
+__END_DECLS
+#define rpc_createerr (*(__rpc_createerr()))
+#else
extern struct rpc_createerr rpc_createerr;
+#endif /* _THREAD_SAFE */
+
+/*
+ * The simplified interface:
+ * enum clnt_stat
+ * rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
+ * const char *host;
+ * const rpcprog_t prognum;
+ * const rpcvers_t versnum;
+ * const rpcproc_t procnum;
+ * const xdrproc_t inproc, outproc;
+ * const char *in;
+ * char *out;
+ * const char *nettype;
+ */
+__BEGIN_DECLS
+extern enum clnt_stat rpc_call __P((const char *, const rpcprog_t,
+ const rpcvers_t, const rpcproc_t,
+ const xdrproc_t, const char *,
+ const xdrproc_t, char *, const char *));
+__END_DECLS
+/*
+ * RPC broadcast interface
+ * The call is broadcasted to all locally connected nets.
+ *
+ * extern enum clnt_stat
+ * rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ * eachresult, nettype)
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const rpcproc_t proc; -- procedure number
+ * const xdrproc_t xargs; -- xdr routine for args
+ * caddr_t argsp; -- pointer to args
+ * const xdrproc_t xresults; -- xdr routine for results
+ * caddr_t resultsp; -- pointer to results
+ * const resultproc_t eachresult; -- call with each result
+ * const char *nettype; -- Transport type
+ *
+ * For each valid response received, the procedure eachresult is called.
+ * Its form is:
+ * done = eachresult(resp, raddr, nconf)
+ * bool_t done;
+ * caddr_t resp;
+ * struct netbuf *raddr;
+ * struct netconfig *nconf;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast. nconf is the transport
+ * on which the response was received.
+ *
+ * extern enum clnt_stat
+ * rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ * eachresult, inittime, waittime, nettype)
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const rpcproc_t proc; -- procedure number
+ * const xdrproc_t xargs; -- xdr routine for args
+ * caddr_t argsp; -- pointer to args
+ * const xdrproc_t xresults; -- xdr routine for results
+ * caddr_t resultsp; -- pointer to results
+ * const resultproc_t eachresult; -- call with each result
+ * const int inittime; -- how long to wait initially
+ * const int waittime; -- maximum time to wait
+ * const char *nettype; -- Transport type
+ */
+
+typedef bool_t (*resultproc_t) __P((caddr_t, ...));
+
+__BEGIN_DECLS
+extern enum clnt_stat rpc_broadcast __P((const rpcprog_t, const rpcvers_t,
+ const rpcproc_t, const xdrproc_t,
+ caddr_t, const xdrproc_t, caddr_t,
+ const resultproc_t, const char *));
+extern enum clnt_stat rpc_broadcast_exp __P((const rpcprog_t, const rpcvers_t,
+ const rpcproc_t, const xdrproc_t,
+ caddr_t, const xdrproc_t, caddr_t,
+ const resultproc_t, const int,
+ const int, const char *));
+__END_DECLS
-#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
-#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+/* For backward compatibility */
+#include <rpc/clnt_soc.h>
-#endif /* !_RPC_CLNT_H */
+#endif /* !_RPC_CLNT_H_ */
diff --git a/include/rpc/clnt_soc.h b/include/rpc/clnt_soc.h
new file mode 100644
index 000000000000..b6c1bd2300a8
--- /dev/null
+++ b/include/rpc/clnt_soc.h
@@ -0,0 +1,118 @@
+/* $NetBSD: clnt_soc.h,v 1.1 2000/06/02 22:57:55 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ */
+
+#ifndef _RPC_CLNT_SOC_H
+#define _RPC_CLNT_SOC_H
+
+/* derived from clnt_soc.h 1.3 88/12/17 SMI */
+
+/*
+ * All the following declarations are only for backward compatibility
+ * with TS-RPC.
+ */
+
+#include <sys/cdefs.h>
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long prog;
+ * u_long version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clnttcp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+/*
+ * Raw (memory) rpc.
+ */
+__BEGIN_DECLS
+extern CLIENT *clntraw_create __P((u_long, u_long));
+__END_DECLS
+
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntudp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *));
+extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+#endif /* _RPC_CLNT_SOC_H */
diff --git a/include/rpc/clnt_stat.h b/include/rpc/clnt_stat.h
new file mode 100644
index 000000000000..26cb4ffff39c
--- /dev/null
+++ b/include/rpc/clnt_stat.h
@@ -0,0 +1,83 @@
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 1986 - 1991, 1994, 1996, 1997 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * clnt_stat.h - Client side remote procedure call enum
+ *
+ */
+
+#ifndef _RPC_CLNT_STAT_H
+#define _RPC_CLNT_STAT_H
+
+#pragma ident "@(#)clnt_stat.h 1.2 97/04/28 SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum clnt_stat {
+ RPC_SUCCESS = 0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS = 1, /* can't encode arguments */
+ RPC_CANTDECODERES = 2, /* can't decode results */
+ RPC_CANTSEND = 3, /* failure in sending call */
+ RPC_CANTRECV = 4,
+ /* failure in receiving result */
+ RPC_TIMEDOUT = 5, /* call timed out */
+ RPC_INTR = 18, /* call interrupted */
+ RPC_UDERROR = 23, /* recv got uderr indication */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH = 6, /* rpc versions not compatible */
+ RPC_AUTHERROR = 7, /* authentication error */
+ RPC_PROGUNAVAIL = 8, /* program not available */
+ RPC_PROGVERSMISMATCH = 9, /* program version mismatched */
+ RPC_PROCUNAVAIL = 10, /* procedure unavailable */
+ RPC_CANTDECODEARGS = 11, /* decode arguments error */
+ RPC_SYSTEMERROR = 12, /* generic "other problem" */
+
+ /*
+ * rpc_call & clnt_create errors
+ */
+ RPC_UNKNOWNHOST = 13, /* unknown host name */
+ RPC_UNKNOWNPROTO = 17, /* unknown protocol */
+ RPC_UNKNOWNADDR = 19, /* Remote address unknown */
+ RPC_NOBROADCAST = 21, /* Broadcasting not supported */
+
+ /*
+ * rpcbind errors
+ */
+ RPC_RPCBFAILURE = 14, /* the pmapper failed in its call */
+#define RPC_PMAPFAILURE RPC_RPCBFAILURE
+ RPC_PROGNOTREGISTERED = 15, /* remote program is not registered */
+ RPC_N2AXLATEFAILURE = 22,
+ /* Name to address translation failed */
+ /*
+ * Misc error in the TLI library
+ */
+ RPC_TLIERROR = 20,
+ /*
+ * unspecified error
+ */
+ RPC_FAILED = 16,
+ /*
+ * asynchronous errors
+ */
+ RPC_INPROGRESS = 24,
+ RPC_STALERACHANDLE = 25,
+ RPC_CANTCONNECT = 26, /* couldn't make connection (cots) */
+ RPC_XPRTFAILED = 27, /* received discon from remote (cots) */
+ RPC_CANTCREATESTREAM = 28 /* can't push rpc module (cots) */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_RPC_CLNT_STAT_H */
diff --git a/include/rpc/des_crypt.h b/include/rpc/des_crypt.h
index c223cd1b77f0..ce6c1bf44783 100644
--- a/include/rpc/des_crypt.h
+++ b/include/rpc/des_crypt.h
@@ -33,6 +33,16 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * des_crypt.h, des library routine interface
+ */
+
+#ifndef _DES_DES_CRYPT_H
+#define _DES_DES_CRYPT_H
#include <sys/cdefs.h>
#include <rpc/rpc.h>
@@ -75,46 +85,22 @@
* Cipher Block Chaining mode
*/
__BEGIN_DECLS
-#ifdef __STDC__
int cbc_crypt __P(( char *, char *, unsigned int, unsigned int, char *));
-#else
-cbc_crypt(/* key, buf, len, mode, ivec */); /*
- char *key;
- char *buf;
- unsigned len;
- unsigned mode;
- char *ivec;
-*/
-#endif
+__END_DECLS
/*
* Electronic Code Book mode
*/
-#ifdef __STDC__
+__BEGIN_DECLS
int ecb_crypt __P(( char *, char *, unsigned int, unsigned int ));
-#else
-ecb_crypt(/* key, buf, len, mode */); /*
- char *key;
- char *buf;
- unsigned len;
- unsigned mode;
-*/
-#endif
__END_DECLS
-#ifndef _KERNEL
/*
* Set des parity for a key.
* DES parity is odd and in the low bit of each byte
*/
__BEGIN_DECLS
-#ifdef __STDC__
void des_setparity __P(( char *));
-#else
-void
-des_setparity(/* key */); /*
- char *key;
-*/
-#endif
__END_DECLS
-#endif
+
+#endif /* _DES_DES_CRYPT_H */
diff --git a/include/rpc/nettype.h b/include/rpc/nettype.h
new file mode 100644
index 000000000000..f53c445d6ee3
--- /dev/null
+++ b/include/rpc/nettype.h
@@ -0,0 +1,64 @@
+/* $NetBSD: nettype.h,v 1.2 2000/07/06 03:17:19 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * nettype.h, Nettype definitions.
+ * All for the topmost layer of rpc
+ *
+ */
+
+#ifndef _RPC_NETTYPE_H
+#define _RPC_NETTYPE_H
+
+#include <netconfig.h>
+
+#define _RPC_NONE 0
+#define _RPC_NETPATH 1
+#define _RPC_VISIBLE 2
+#define _RPC_CIRCUIT_V 3
+#define _RPC_DATAGRAM_V 4
+#define _RPC_CIRCUIT_N 5
+#define _RPC_DATAGRAM_N 6
+#define _RPC_TCP 7
+#define _RPC_UDP 8
+
+__BEGIN_DECLS
+extern void *__rpc_setconf __P((const char *));
+extern void __rpc_endconf __P((void *));
+extern struct netconfig *__rpc_getconf __P((void *));
+extern struct netconfig *__rpc_getconfip __P((const char *));
+__END_DECLS
+
+#endif /* !_RPC_NETTYPE_H */
diff --git a/include/rpc/pmap_clnt.h b/include/rpc/pmap_clnt.h
index d4080cc2857a..a2beae5691ce 100644
--- a/include/rpc/pmap_clnt.h
+++ b/include/rpc/pmap_clnt.h
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_clnt.h,v 1.9 2000/06/02 22:57:55 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,7 +28,7 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*
- * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
+ * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
* from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
*/
@@ -60,8 +62,8 @@
* address if the responder to the broadcast.
*/
-#ifndef _RPC_PMAPCLNT_H
-#define _RPC_PMAPCLNT_H
+#ifndef _RPC_PMAP_CLNT_H_
+#define _RPC_PMAP_CLNT_H_
#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -76,10 +78,9 @@ extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *,
extern enum clnt_stat clnt_broadcast __P((u_long, u_long, u_long,
xdrproc_t, char *,
xdrproc_t, char *,
- bool_t (*) __P((caddr_t,
- struct sockaddr_in *))));
+ resultproc_t));
extern u_short pmap_getport __P((struct sockaddr_in *,
u_long, u_long, u_int));
__END_DECLS
-#endif /* !_RPC_PMAPCLNT_H */
+#endif /* !_RPC_PMAP_CLNT_H_ */
diff --git a/include/rpc/pmap_prot.h b/include/rpc/pmap_prot.h
index 123ee159dfae..7dddab2e0d5b 100644
--- a/include/rpc/pmap_prot.h
+++ b/include/rpc/pmap_prot.h
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_prot.h,v 1.8 2000/06/02 22:57:55 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,7 +28,7 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*
- * from: @(#)pmap_prot.h 1.14 88/02/08 SMI
+ * from: @(#)pmap_prot.h 1.14 88/02/08 SMI
* from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
*/
@@ -68,8 +70,8 @@
* The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
*/
-#ifndef _RPC_PMAPPROT_H
-#define _RPC_PMAPPROT_H
+#ifndef _RPC_PMAP_PROT_H
+#define _RPC_PMAP_PROT_H
#include <sys/cdefs.h>
#define PMAPPORT ((u_short)111)
@@ -99,6 +101,7 @@ struct pmaplist {
__BEGIN_DECLS
extern bool_t xdr_pmap __P((XDR *, struct pmap *));
extern bool_t xdr_pmaplist __P((XDR *, struct pmaplist **));
+extern bool_t xdr_pmaplist_ptr __P((XDR *, struct pmaplist *));
__END_DECLS
-#endif /* !_RPC_PMAPPROT_H */
+#endif /* !_RPC_PMAP_PROT_H */
diff --git a/include/rpc/pmap_rmt.h b/include/rpc/pmap_rmt.h
index 845e815e0add..4361f0d0b4f7 100644
--- a/include/rpc/pmap_rmt.h
+++ b/include/rpc/pmap_rmt.h
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_rmt.h,v 1.7 1998/02/11 23:01:23 lukem Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -38,8 +40,8 @@
* Copyright (C) 1986, Sun Microsystems, Inc.
*/
-#ifndef _RPC_PMAPRMT_H
-#define _RPC_PMAPRMT_H
+#ifndef _RPC_PMAP_RMT_H
+#define _RPC_PMAP_RMT_H
#include <sys/cdefs.h>
struct rmtcallargs {
@@ -60,4 +62,4 @@ extern bool_t xdr_rmtcall_args __P((XDR *, struct rmtcallargs *));
extern bool_t xdr_rmtcallres __P((XDR *, struct rmtcallres *));
__END_DECLS
-#endif /* !_RPC_PMAPRMT_H */
+#endif /* !_RPC_PMAP_RMT_H */
diff --git a/include/rpc/raw.h b/include/rpc/raw.h
new file mode 100644
index 000000000000..0fea4ad087a2
--- /dev/null
+++ b/include/rpc/raw.h
@@ -0,0 +1,58 @@
+/* $NetBSD: raw.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_RAW_H
+#define _RPC_RAW_H
+
+/* from: @(#)raw.h 1.11 94/04/25 SMI */
+/* from: @(#)raw.h 1.2 88/10/25 SMI */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * raw.h
+ *
+ * Raw interface
+ * The common memory area over which they will communicate
+ */
+extern char *__rpc_rawcombuf;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPC_RAW_H */
diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h
index 7fd4a7f85906..8a45c4928096 100644
--- a/include/rpc/rpc.h
+++ b/include/rpc/rpc.h
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc.h,v 1.13 2000/06/02 22:57:56 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -41,6 +43,7 @@
#define _RPC_RPC_H
#include <rpc/types.h> /* some typedefs */
+#include <sys/socket.h>
#include <netinet/in.h>
/* external data representation interfaces */
@@ -65,30 +68,40 @@
#include <rpc/svc.h> /* service manager and multiplexer */
#include <rpc/svc_auth.h> /* service side authenticator */
-/*
- * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON
- * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will
- * already have the structures defined by <rpc/netdb.h> included in <netdb.h>.
- */
-/* routines for parsing /etc/rpc */
+/* Portmapper client, server, and protocol headers */
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
-struct rpcent {
- char *r_name; /* name of server for this rpc program */
- char **r_aliases; /* alias list */
- int r_number; /* rpc program number */
-};
+#include <rpc/rpcb_clnt.h> /* rpcbind interface functions */
-__BEGIN_DECLS
-extern struct rpcent *getrpcbyname __P((char *));
-extern struct rpcent *getrpcbynumber __P((int));
-extern struct rpcent *getrpcent __P((void));
-extern int getrpcport __P((char *host, int prognum, int versnum, int proto));
-extern void setrpcent __P((int));
-extern void endrpcent __P((void));
+#include <rpc/rpcent.h>
+__BEGIN_DECLS
+extern int get_myaddress __P((struct sockaddr_in *));
extern int bindresvport __P((int, struct sockaddr_in *));
+extern int registerrpc __P((int, int, int, char *(*) __P((char [UDPMSGSIZE])),
+ xdrproc_t, xdrproc_t));
+extern int callrpc __P((char *, int, int, int, xdrproc_t, char *,
+ xdrproc_t , char *));
+extern int getrpcport __P((char *, int, int, int));
+
+char *taddr2uaddr __P((const struct netconfig *, const struct netbuf *));
+struct netbuf *uaddr2taddr __P((const struct netconfig *, const char *));
+
+struct sockaddr;
extern int bindresvport_sa __P((int, struct sockaddr *));
-extern int get_myaddress __P((struct sockaddr_in *));
+__END_DECLS
+
+/*
+ * The following are not exported interfaces, they are for internal library
+ * and rpcbind use only. Do not use, they may change without notice.
+ */
+__BEGIN_DECLS
+int __rpc_nconf2fd __P((const struct netconfig *));
+int __rpc_nconf2sockinfo __P((const struct netconfig *,
+ struct __rpc_sockinfo *));
+int __rpc_fd2sockinfo __P((int, struct __rpc_sockinfo *));
+u_int __rpc_get_t_size __P((int, int, int));
__END_DECLS
#endif /* !_RPC_RPC_H */
diff --git a/include/rpc/rpc_com.h b/include/rpc/rpc_com.h
index 2cf5995d2d70..8add5d4c6a03 100644
--- a/include/rpc/rpc_com.h
+++ b/include/rpc/rpc_com.h
@@ -1,3 +1,6 @@
+/* $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ */
+/* $FreeBSD$ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -39,40 +42,42 @@
#ifndef _RPC_RPCCOM_H
#define _RPC_RPCCOM_H
-/* From: #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */
+#include <sys/cdefs.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+/* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */
/*
- * File descriptor to be used on xxx_create calls to get default descriptor
- */
-#define RPC_ANYSOCK -1
-#define RPC_ANYFD RPC_ANYSOCK
-/*
* The max size of the transport, if the size cannot be determined
* by other means.
*/
#define RPC_MAXDATASIZE 9000
#define RPC_MAXADDRSIZE 1024
-#if defined(__STDC__) || defined(__cplusplus)
-extern u_int __rpc_get_t_size (int, long);
-extern u_int __rpc_get_a_size (long);
-extern int __rpc_dtbsize (void);
-extern int _rpc_dtablesize (void);
-extern int _rpc_get_default_domain(char **);
-#else
-extern u_int __rpc_get_t_size ();
-extern u_int __rpc_get_a_size ();
-extern int __rpc_dtbsize ();
-extern int _rpc_dtablesize ();
-extern int _rpc_get_default_domain();
-#endif
+#define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \
+ (u_int32_t)(now)->tv_usec)
+
+__BEGIN_DECLS
+extern u_int __rpc_get_a_size __P((int));
+extern int __rpc_dtbsize __P((void));
+extern struct netconfig * __rpcgettp __P((int));
+extern int __rpc_get_default_domain __P((char **));
+
+char *__rpc_taddr2uaddr_af __P((int, const struct netbuf *));
+struct netbuf *__rpc_uaddr2taddr_af __P((int, const char *));
+int __rpc_fixup_addr __P((struct netbuf *, const struct netbuf *));
+int __rpc_sockinfo2netid __P((struct __rpc_sockinfo *, const char **));
+int __rpc_seman2socktype __P((int));
+int __rpc_socktype2seman __P((int));
+void *rpc_nullproc __P((CLIENT *));
+int __rpc_sockisbound __P((int));
+
+struct netbuf *__rpcb_findaddr __P((rpcprog_t, rpcvers_t,
+ const struct netconfig *,
+ const char *, CLIENT **));
+bool_t __rpc_control __P((int,void *));
+
+char *_get_next_token __P((char *, int));
-#ifdef __cplusplus
-}
-#endif
+__END_DECLS
#endif /* _RPC_RPCCOM_H */
diff --git a/include/rpc/rpc_msg.h b/include/rpc/rpc_msg.h
index 98f0f79aa881..ed634a180250 100644
--- a/include/rpc/rpc_msg.h
+++ b/include/rpc/rpc_msg.h
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc_msg.h,v 1.11 2000/06/02 22:57:56 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -38,10 +40,10 @@
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
-#ifndef _RPC_RPCMSG_H
-#define _RPC_RPCMSG_H
+#ifndef _RPC_RPC_MSG_H
+#define _RPC_RPC_MSG_H
-#define RPC_MSG_VERSION ((u_long) 2)
+#define RPC_MSG_VERSION ((u_int32_t) 2)
#define RPC_SERVICE_PORT ((u_short) 2048)
/*
@@ -88,8 +90,8 @@ struct accepted_reply {
enum accept_stat ar_stat;
union {
struct {
- u_int32_t low;
- u_int32_t high;
+ rpcvers_t low;
+ rpcvers_t high;
} AR_versions;
struct {
caddr_t where;
@@ -108,8 +110,8 @@ struct rejected_reply {
enum reject_stat rj_stat;
union {
struct {
- u_int32_t low;
- u_int32_t high;
+ rpcvers_t low;
+ rpcvers_t high;
} RJ_versions;
enum auth_stat RJ_why; /* why authentication did not work */
} ru;
@@ -134,10 +136,10 @@ struct reply_body {
* Body of an rpc request call.
*/
struct call_body {
- u_int32_t cb_rpcvers; /* must be equal to two */
- u_int32_t cb_prog;
- u_int32_t cb_vers;
- u_int32_t cb_proc;
+ rpcvers_t cb_rpcvers; /* must be equal to two */
+ rpcprog_t cb_prog;
+ rpcvers_t cb_vers;
+ rpcproc_t cb_proc;
struct opaque_auth cb_cred;
struct opaque_auth cb_verf; /* protocol specific - provided by client */
};
@@ -183,14 +185,30 @@ extern bool_t xdr_callhdr __P((XDR *, struct rpc_msg *));
*/
extern bool_t xdr_replymsg __P((XDR *, struct rpc_msg *));
+
+/*
+ * XDR routine to handle a accepted rpc reply.
+ * xdr_accepted_reply(xdrs, rej)
+ * XDR *xdrs;
+ * struct accepted_reply *rej;
+ */
+extern bool_t xdr_accepted_reply __P((XDR *, struct accepted_reply *));
+
+/*
+ * XDR routine to handle a rejected rpc reply.
+ * xdr_rejected_reply(xdrs, rej)
+ * XDR *xdrs;
+ * struct rejected_reply *rej;
+ */
+extern bool_t xdr_rejected_reply __P((XDR *, struct rejected_reply *));
+
/*
* Fills in the error part of a reply message.
* _seterr_reply(msg, error)
* struct rpc_msg *msg;
* struct rpc_err *error;
*/
-struct rpc_err;
extern void _seterr_reply __P((struct rpc_msg *, struct rpc_err *));
__END_DECLS
-#endif /* !_RPC_RPCMSG_H */
+#endif /* !_RPC_RPC_MSG_H */
diff --git a/include/rpc/rpcb_clnt.h b/include/rpc/rpcb_clnt.h
new file mode 100644
index 000000000000..0f081a47b0c3
--- /dev/null
+++ b/include/rpc/rpcb_clnt.h
@@ -0,0 +1,85 @@
+/* $NetBSD: rpcb_clnt.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcb_clnt.h
+ * Supplies C routines to get to rpcbid services.
+ *
+ */
+
+/*
+ * Usage:
+ * success = rpcb_set(program, version, nconf, address);
+ * success = rpcb_unset(program, version, nconf);
+ * success = rpcb_getaddr(program, version, nconf, host);
+ * head = rpcb_getmaps(nconf, host);
+ * clnt_stat = rpcb_rmtcall(nconf, host, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, addr_ptr)
+ * success = rpcb_gettime(host, timep)
+ * uaddr = rpcb_taddr2uaddr(nconf, taddr);
+ * taddr = rpcb_uaddr2uaddr(nconf, uaddr);
+ */
+
+#ifndef _RPC_RPCB_CLNT_H
+#define _RPC_RPCB_CLNT_H
+
+/* #pragma ident "@(#)rpcb_clnt.h 1.13 94/04/25 SMI" */
+/* rpcb_clnt.h 1.3 88/12/05 SMI */
+
+#include <rpc/types.h>
+#include <rpc/rpcb_prot.h>
+
+__BEGIN_DECLS
+extern bool_t rpcb_set __P((const rpcprog_t, const rpcvers_t,
+ const struct netconfig *, const struct netbuf *));
+extern bool_t rpcb_unset __P((const rpcprog_t, const rpcvers_t,
+ const struct netconfig *));
+extern rpcblist *rpcb_getmaps __P((const struct netconfig *, const char *));
+extern enum clnt_stat rpcb_rmtcall __P((const struct netconfig *,
+ const char *, const rpcprog_t,
+ const rpcvers_t, const rpcproc_t,
+ const xdrproc_t, const caddr_t,
+ const xdrproc_t, const caddr_t,
+ const struct timeval,
+ const struct netbuf *));
+extern bool_t rpcb_getaddr __P((const rpcprog_t, const rpcvers_t,
+ const struct netconfig *, struct netbuf *,
+ const char *));
+extern bool_t rpcb_gettime __P((const char *, time_t *));
+extern char *rpcb_taddr2uaddr __P((struct netconfig *, struct netbuf *));
+extern struct netbuf *rpcb_uaddr2taddr __P((struct netconfig *, char *));
+__END_DECLS
+
+#endif /* !_RPC_RPCB_CLNT_H */
diff --git a/include/rpc/rpcb_prot.x b/include/rpc/rpcb_prot.x
new file mode 100644
index 000000000000..b1ab096b40b0
--- /dev/null
+++ b/include/rpc/rpcb_prot.x
@@ -0,0 +1,554 @@
+%/*
+% * $FreeBSD$
+% *
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+%/*
+% * Copyright (c) 1988 by Sun Microsystems, Inc.
+% */
+
+%/* from rpcb_prot.x */
+
+#ifdef RPC_HDR
+%
+%/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */
+%
+%#ifndef _KERNEL
+%
+#endif
+
+/*
+ * rpcb_prot.x
+ * rpcbind protocol, versions 3 and 4, in RPC Language
+ */
+%
+%/*
+% * The following procedures are supported by the protocol in version 3:
+% *
+% * RPCBPROC_NULL() returns ()
+% * takes nothing, returns nothing
+% *
+% * RPCBPROC_SET(rpcb) returns (bool_t)
+% * TRUE is success, FALSE is failure. Registers the tuple
+% * [prog, vers, address, owner, netid].
+% * Finds out owner and netid information on its own.
+% *
+% * RPCBPROC_UNSET(rpcb) returns (bool_t)
+% * TRUE is success, FALSE is failure. Un-registers tuple
+% * [prog, vers, netid]. addresses is ignored.
+% * If netid is NULL, unregister all.
+% *
+% * RPCBPROC_GETADDR(rpcb) returns (string).
+% * 0 is failure. Otherwise returns the universal address where the
+% * triple [prog, vers, netid] is registered. Ignore address and owner.
+% *
+% * RPCBPROC_DUMP() RETURNS (rpcblist_ptr)
+% * used to dump the entire rpcbind maps
+% *
+% * RPCBPROC_CALLIT(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure is quiet; i.e. it does not return error information!!!
+% * This routine only passes null authentication parameters.
+% * It has no interface to xdr routines for RPCBPROC_CALLIT.
+% *
+% * RPCBPROC_GETTIME() returns (int).
+% * Gets the remote machines time
+% *
+% * RPCBPROC_UADDR2TADDR(strint) RETURNS (struct netbuf)
+% * Returns the netbuf address from universal address.
+% *
+% * RPCBPROC_TADDR2UADDR(struct netbuf) RETURNS (string)
+% * Returns the universal address from netbuf address.
+% *
+% * END OF RPCBIND VERSION 3 PROCEDURES
+% */
+%/*
+% * Except for RPCBPROC_CALLIT, the procedures above are carried over to
+% * rpcbind version 4. Those below are added or modified for version 4.
+% * NOTE: RPCBPROC_BCAST HAS THE SAME FUNCTIONALITY AND PROCEDURE NUMBER
+% * AS RPCBPROC_CALLIT.
+% *
+% * RPCBPROC_BCAST(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure IS quiet; i.e. it DOES NOT return error information!!!
+% * This routine should be used for broadcasting and nothing else.
+% *
+% * RPCBPROC_GETVERSADDR(rpcb) returns (string).
+% * 0 is failure. Otherwise returns the universal address where the
+% * triple [prog, vers, netid] is registered. Ignore address and owner.
+% * Same as RPCBPROC_GETADDR except that if the given version number
+% * is not available, the address is not returned.
+% *
+% * RPCBPROC_INDIRECT(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure is NOT quiet; i.e. it DOES return error information!!!
+% * as any normal application would expect.
+% *
+% * RPCBPROC_GETADDRLIST(rpcb) returns (rpcb_entry_list_ptr).
+% * Same as RPCBPROC_GETADDR except that it returns a list of all the
+% * addresses registered for the combination (prog, vers) (for all
+% * transports).
+% *
+% * RPCBPROC_GETSTAT(void) returns (rpcb_stat_byvers)
+% * Returns the statistics about the kind of requests received by rpcbind.
+% */
+%
+%/*
+% * A mapping of (program, version, network ID) to address
+% */
+struct rpcb {
+ rpcprog_t r_prog; /* program number */
+ rpcvers_t r_vers; /* version number */
+ string r_netid<>; /* network id */
+ string r_addr<>; /* universal address */
+ string r_owner<>; /* owner of this service */
+};
+#ifdef RPC_HDR
+%
+%typedef rpcb RPCB;
+%
+#endif
+%
+%/*
+% * A list of mappings
+% *
+% * Below are two definitions for the rpcblist structure. This is done because
+% * xdr_rpcblist() is specified to take a struct rpcblist **, rather than a
+% * struct rpcblist * that rpcgen would produce. One version of the rpcblist
+% * structure (actually called rp__list) is used with rpcgen, and the other is
+% * defined only in the header file for compatibility with the specified
+% * interface.
+% */
+
+struct rp__list {
+ rpcb rpcb_map;
+ struct rp__list *rpcb_next;
+};
+
+typedef rp__list *rpcblist_ptr; /* results of RPCBPROC_DUMP */
+
+#ifdef RPC_HDR
+%
+%typedef struct rp__list rpcblist;
+%typedef struct rp__list RPCBLIST;
+%
+%#ifndef __cplusplus
+%struct rpcblist {
+% RPCB rpcb_map;
+% struct rpcblist *rpcb_next;
+%};
+%#endif
+%
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%extern bool_t xdr_rpcblist(XDR *, rpcblist**);
+%#ifdef __cplusplus
+%}
+%#endif
+%
+#endif
+
+%
+%/*
+% * Arguments of remote calls
+% */
+struct rpcb_rmtcallargs {
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ rpcproc_t proc; /* procedure number */
+ opaque args<>; /* argument */
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rpcb_rmtcallargs structure.
+% *
+% * The routine that XDRs the rpcb_rmtcallargs structure must deal with the
+% * opaque arguments in the "args" structure. xdr_rpcb_rmtcallargs() needs to
+% * be passed the XDR routine that knows the args' structure. This routine
+% * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since
+% * the application being called already knows the args structure. So we use a
+% * different "XDR" structure on the client side, r_rpcb_rmtcallargs, which
+% * includes the args' XDR routine.
+% */
+%struct r_rpcb_rmtcallargs {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% rpcproc_t proc;
+% struct {
+% u_int args_len;
+% char *args_val;
+% } args;
+% xdrproc_t xdr_args; /* encodes args */
+%};
+%
+#endif /* def RPC_HDR */
+%
+%/*
+% * Results of the remote call
+% */
+struct rpcb_rmtcallres {
+ string addr<>; /* remote universal address */
+ opaque results<>; /* result */
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rpcb_rmtcallres structure.
+% */
+%struct r_rpcb_rmtcallres {
+% char *addr;
+% struct {
+% u_int32_t results_len;
+% char *results_val;
+% } results;
+% xdrproc_t xdr_res; /* decodes results */
+%};
+#endif RPC_HDR
+%
+%/*
+% * rpcb_entry contains a merged address of a service on a particular
+% * transport, plus associated netconfig information. A list of rpcb_entrys
+% * is returned by RPCBPROC_GETADDRLIST. See netconfig.h for values used
+% * in r_nc_* fields.
+% */
+struct rpcb_entry {
+ string r_maddr<>; /* merged address of service */
+ string r_nc_netid<>; /* netid field */
+ unsigned int r_nc_semantics; /* semantics of transport */
+ string r_nc_protofmly<>; /* protocol family */
+ string r_nc_proto<>; /* protocol name */
+};
+%
+%/*
+% * A list of addresses supported by a service.
+% */
+struct rpcb_entry_list {
+ rpcb_entry rpcb_entry_map;
+ struct rpcb_entry_list *rpcb_entry_next;
+};
+
+typedef rpcb_entry_list *rpcb_entry_list_ptr;
+
+%
+%/*
+% * rpcbind statistics
+% */
+%
+const rpcb_highproc_2 = RPCBPROC_CALLIT;
+const rpcb_highproc_3 = RPCBPROC_TADDR2UADDR;
+const rpcb_highproc_4 = RPCBPROC_GETSTAT;
+
+const RPCBSTAT_HIGHPROC = 13; /* # of procs in rpcbind V4 plus one */
+const RPCBVERS_STAT = 3; /* provide only for rpcbind V2, V3 and V4 */
+const RPCBVERS_4_STAT = 2;
+const RPCBVERS_3_STAT = 1;
+const RPCBVERS_2_STAT = 0;
+%
+%/* Link list of all the stats about getport and getaddr */
+struct rpcbs_addrlist {
+ rpcprog_t prog;
+ rpcvers_t vers;
+ int success;
+ int failure;
+ string netid<>;
+ struct rpcbs_addrlist *next;
+};
+%
+%/* Link list of all the stats about rmtcall */
+struct rpcbs_rmtcalllist {
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc;
+ int success;
+ int failure;
+ int indirect; /* whether callit or indirect */
+ string netid<>;
+ struct rpcbs_rmtcalllist *next;
+};
+
+typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+
+struct rpcb_stat {
+ rpcbs_proc info;
+ int setinfo;
+ int unsetinfo;
+ rpcbs_addrlist_ptr addrinfo;
+ rpcbs_rmtcalllist_ptr rmtinfo;
+};
+%
+%/*
+% * One rpcb_stat structure is returned for each version of rpcbind
+% * being monitored.
+% */
+
+typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+
+#ifdef RPC_HDR
+%
+%/*
+% * We don't define netbuf in RPCL, since it would contain structure member
+% * names that would conflict with the definition of struct netbuf in
+% * <tiuser.h>. Instead we merely declare the XDR routine xdr_netbuf() here,
+% * and implement it ourselves in rpc/rpcb_prot.c.
+% */
+%#ifdef __cplusplus
+%extern "C" bool_t xdr_netbuf(XDR *, struct netbuf *);
+%
+%#else __STDC__
+%extern bool_t xdr_netbuf(XDR *, struct netbuf *);
+%
+%#endif
+#endif /* def RPC_HDR */
+
+/*
+ * rpcbind procedures
+ */
+program RPCBPROG {
+ version RPCBVERS {
+ bool
+ RPCBPROC_SET(rpcb) = 1;
+
+ bool
+ RPCBPROC_UNSET(rpcb) = 2;
+
+ string
+ RPCBPROC_GETADDR(rpcb) = 3;
+
+ rpcblist_ptr
+ RPCBPROC_DUMP(void) = 4;
+
+ rpcb_rmtcallres
+ RPCBPROC_CALLIT(rpcb_rmtcallargs) = 5;
+
+ unsigned int
+ RPCBPROC_GETTIME(void) = 6;
+
+ struct netbuf
+ RPCBPROC_UADDR2TADDR(string) = 7;
+
+ string
+ RPCBPROC_TADDR2UADDR(struct netbuf) = 8;
+ } = 3;
+
+ version RPCBVERS4 {
+ bool
+ RPCBPROC_SET(rpcb) = 1;
+
+ bool
+ RPCBPROC_UNSET(rpcb) = 2;
+
+ string
+ RPCBPROC_GETADDR(rpcb) = 3;
+
+ rpcblist_ptr
+ RPCBPROC_DUMP(void) = 4;
+
+ /*
+ * NOTE: RPCBPROC_BCAST has the same functionality as CALLIT;
+ * the new name is intended to indicate that this
+ * procedure should be used for broadcast RPC, and
+ * RPCBPROC_INDIRECT should be used for indirect calls.
+ */
+ rpcb_rmtcallres
+ RPCBPROC_BCAST(rpcb_rmtcallargs) = RPCBPROC_CALLIT;
+
+ unsigned int
+ RPCBPROC_GETTIME(void) = 6;
+
+ struct netbuf
+ RPCBPROC_UADDR2TADDR(string) = 7;
+
+ string
+ RPCBPROC_TADDR2UADDR(struct netbuf) = 8;
+
+ string
+ RPCBPROC_GETVERSADDR(rpcb) = 9;
+
+ rpcb_rmtcallres
+ RPCBPROC_INDIRECT(rpcb_rmtcallargs) = 10;
+
+ rpcb_entry_list_ptr
+ RPCBPROC_GETADDRLIST(rpcb) = 11;
+
+ rpcb_stat_byvers
+ RPCBPROC_GETSTAT(void) = 12;
+ } = 4;
+} = 100000;
+#ifdef RPC_HDR
+%
+%#define RPCBVERS_3 RPCBVERS
+%#define RPCBVERS_4 RPCBVERS4
+%
+%#define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock"
+%
+%#else /* ndef _KERNEL */
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%
+%/*
+% * A mapping of (program, version, network ID) to address
+% */
+%struct rpcb {
+% rpcprog_t r_prog; /* program number */
+% rpcvers_t r_vers; /* version number */
+% char *r_netid; /* network id */
+% char *r_addr; /* universal address */
+% char *r_owner; /* owner of the mapping */
+%};
+%typedef struct rpcb RPCB;
+%
+%/*
+% * A list of mappings
+% */
+%struct rpcblist {
+% RPCB rpcb_map;
+% struct rpcblist *rpcb_next;
+%};
+%typedef struct rpcblist RPCBLIST;
+%typedef struct rpcblist *rpcblist_ptr;
+%
+%/*
+% * Remote calls arguments
+% */
+%struct rpcb_rmtcallargs {
+% rpcprog_t prog; /* program number */
+% rpcvers_t vers; /* version number */
+% rpcproc_t proc; /* procedure number */
+% u_int32_t arglen; /* arg len */
+% caddr_t args_ptr; /* argument */
+% xdrproc_t xdr_args; /* XDR routine for argument */
+%};
+%typedef struct rpcb_rmtcallargs rpcb_rmtcallargs;
+%
+%/*
+% * Remote calls results
+% */
+%struct rpcb_rmtcallres {
+% char *addr_ptr; /* remote universal address */
+% u_int32_t resultslen; /* results length */
+% caddr_t results_ptr; /* results */
+% xdrproc_t xdr_results; /* XDR routine for result */
+%};
+%typedef struct rpcb_rmtcallres rpcb_rmtcallres;
+%
+%struct rpcb_entry {
+% char *r_maddr;
+% char *r_nc_netid;
+% unsigned int r_nc_semantics;
+% char *r_nc_protofmly;
+% char *r_nc_proto;
+%};
+%typedef struct rpcb_entry rpcb_entry;
+%
+%/*
+% * A list of addresses supported by a service.
+% */
+%
+%struct rpcb_entry_list {
+% rpcb_entry rpcb_entry_map;
+% struct rpcb_entry_list *rpcb_entry_next;
+%};
+%typedef struct rpcb_entry_list rpcb_entry_list;
+%
+%typedef rpcb_entry_list *rpcb_entry_list_ptr;
+%
+%/*
+% * rpcbind statistics
+% */
+%
+%#define rpcb_highproc_2 RPCBPROC_CALLIT
+%#define rpcb_highproc_3 RPCBPROC_TADDR2UADDR
+%#define rpcb_highproc_4 RPCBPROC_GETSTAT
+%#define RPCBSTAT_HIGHPROC 13
+%#define RPCBVERS_STAT 3
+%#define RPCBVERS_4_STAT 2
+%#define RPCBVERS_3_STAT 1
+%#define RPCBVERS_2_STAT 0
+%
+%/* Link list of all the stats about getport and getaddr */
+%
+%struct rpcbs_addrlist {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% int success;
+% int failure;
+% char *netid;
+% struct rpcbs_addrlist *next;
+%};
+%typedef struct rpcbs_addrlist rpcbs_addrlist;
+%
+%/* Link list of all the stats about rmtcall */
+%
+%struct rpcbs_rmtcalllist {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% rpcproc_t proc;
+% int success;
+% int failure;
+% int indirect;
+% char *netid;
+% struct rpcbs_rmtcalllist *next;
+%};
+%typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist;
+%
+%typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+%
+%typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+%
+%typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+%
+%struct rpcb_stat {
+% rpcbs_proc info;
+% int setinfo;
+% int unsetinfo;
+% rpcbs_addrlist_ptr addrinfo;
+% rpcbs_rmtcalllist_ptr rmtinfo;
+%};
+%typedef struct rpcb_stat rpcb_stat;
+%
+%/*
+% * One rpcb_stat structure is returned for each version of rpcbind
+% * being monitored.
+% */
+%
+%typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+%
+%#ifdef __cplusplus
+%}
+%#endif
+%
+%#endif /* ndef _KERNEL */
+#endif /* RPC_HDR */
diff --git a/include/rpc/rpcent.h b/include/rpc/rpcent.h
new file mode 100644
index 000000000000..234002ac6a9c
--- /dev/null
+++ b/include/rpc/rpcent.h
@@ -0,0 +1,69 @@
+/* $NetBSD: rpcent.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcent.h,
+ * For converting rpc program numbers to names etc.
+ *
+ */
+
+#ifndef _RPC_RPCENT_H
+#define _RPC_RPCENT_H
+
+/* #pragma ident "@(#)rpcent.h 1.13 94/04/25 SMI" */
+/* @(#)rpcent.h 1.1 88/12/06 SMI */
+
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+__BEGIN_DECLS
+extern struct rpcent *getrpcbyname_r __P((const char *, struct rpcent *,
+ char *, int));
+extern struct rpcent *getrpcbynumber_r __P((int, struct rpcent *, char *, int));
+extern struct rpcent *getrpcent_r __P((struct rpcent *, char *, int));
+
+/* Old interfaces that return a pointer to a static area; MT-unsafe */
+extern struct rpcent *getrpcbyname __P((char *));
+extern struct rpcent *getrpcbynumber __P((int));
+extern struct rpcent *getrpcent __P((void));
+extern void setrpcent __P((int));
+extern void endrpcent __P((void));
+__END_DECLS
+
+#endif /* !_RPC_CENT_H */
diff --git a/include/rpc/svc.h b/include/rpc/svc.h
index 9ef76cfb22d9..dc03f5934f71 100644
--- a/include/rpc/svc.h
+++ b/include/rpc/svc.h
@@ -1,3 +1,5 @@
+/* $NetBSD: svc.h,v 1.17 2000/06/02 22:57:56 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,15 +28,15 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*
- * from: @(#)svc.h 1.20 88/02/08 SMI
- * from: @(#)svc.h 2.2 88/07/29 4.0 RPCSRC
+ * from: @(#)svc.h 1.35 88/12/17 SMI
+ * from: @(#)svc.h 1.27 94/04/25 SMI
* $FreeBSD$
*/
/*
* svc.h, Server-side remote procedure call interface.
*
- * Copyright (C) 1984, Sun Microsystems, Inc.
+ * Copyright (C) 1986-1993 by Sun Microsystems, Inc.
*/
#ifndef _RPC_SVC_H
@@ -63,21 +65,26 @@
* parameters, struct svc_req * and SVCXPRT *, defined below.
*/
+/*
+ * Service control requests
+ */
+#define SVCGET_VERSQUIET 1
+#define SVCSET_VERSQUIET 2
+
+
enum xprt_stat {
XPRT_DIED,
XPRT_MOREREQS,
XPRT_IDLE
};
-struct rpc_msg;
-
/*
* Server side transport handle
*/
typedef struct __rpc_svcxprt {
- int xp_sock;
+ int xp_fd;
u_short xp_port; /* associated port number */
- struct xp_ops {
+ const struct xp_ops {
/* receive incoming requests */
bool_t (*xp_recv) __P((struct __rpc_svcxprt *,
struct rpc_msg *));
@@ -96,16 +103,45 @@ typedef struct __rpc_svcxprt {
void (*xp_destroy) __P((struct __rpc_svcxprt *));
} *xp_ops;
int xp_addrlen; /* length of remote address */
- struct sockaddr_in xp_raddr; /* remote address */
+ struct sockaddr_in xp_raddr; /* remote addr. (backward ABI compat) */
+ /* XXX - fvdl stick this here for ABI backward compat reasons */
+ const struct xp_ops2 {
+ /* catch-all function */
+ bool_t (*xp_control) __P((struct __rpc_svcxprt *, const u_int,
+ void *));
+ } *xp_ops2;
+ char *xp_tp; /* transport provider device name */
+ char *xp_netid; /* network token */
+ 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 */
- caddr_t xp_p2; /* private */
+ void *xp_p1; /* private: for use by svc ops */
+ void *xp_p2; /* private: for use by svc ops */
+ void *xp_p3; /* private: for use by svc lib */
+ int xp_type; /* transport type */
} SVCXPRT;
/*
+ * Service request
+ */
+struct svc_req {
+ u_int32_t rq_prog; /* service program number */
+ u_int32_t rq_vers; /* service protocol version */
+ u_int32_t rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ void *rq_clntcred; /* read only cooked cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+};
+
+/*
* Approved way of getting address of caller
*/
-#define svc_getcaller(x) (&(x)->xp_raddr)
+#define svc_getrpccaller(x) (&(x)->xp_rtaddr)
+
+/*
+ * FreeBSD-only definition to get the creds of the caller (AF_LOCAL).
+ */
+#define __svc_getcallercreds(x) ((struct cmsgcred *)(x)->xp_p2)
/*
* Operations defined on an SVCXPRT handle
@@ -145,44 +181,36 @@ typedef struct __rpc_svcxprt {
#define svc_destroy(xprt) \
(*(xprt)->xp_ops->xp_destroy)(xprt)
-
-/*
- * Service request
- */
-struct svc_req {
- u_int32_t rq_prog; /* service program number */
- u_int32_t rq_vers; /* service protocol version */
- u_int32_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 */
-};
-
+#define SVC_CONTROL(xprt, rq, in) \
+ (*(xprt)->xp_ops2->xp_control)((xprt), (rq), (in))
/*
* Service registration
*
- * svc_register(xprt, prog, vers, dispatch, protocol)
- * SVCXPRT *xprt;
- * u_long prog;
- * u_long vers;
- * void (*dispatch)();
- * int protocol; (like TCP or UDP, zero means do not register)
+ * svc_reg(xprt, prog, vers, dispatch, nconf)
+ * const SVCXPRT *xprt;
+ * const rpcprog_t prog;
+ * const rpcvers_t vers;
+ * const void (*dispatch)();
+ * const struct netconfig *nconf;
*/
+
__BEGIN_DECLS
-extern bool_t svc_register __P((SVCXPRT *, u_long, u_long,
- void (*) __P((struct svc_req *, SVCXPRT *)), int));
+extern bool_t svc_reg __P((SVCXPRT *, const rpcprog_t, const rpcvers_t,
+ void (*) __P((struct svc_req *, SVCXPRT *)),
+ const struct netconfig *));
__END_DECLS
/*
* Service un-registration
*
- * svc_unregister(prog, vers)
- * u_long prog;
- * u_long vers;
+ * svc_unreg(prog, vers)
+ * const rpcprog_t prog;
+ * const rpcvers_t vers;
*/
+
__BEGIN_DECLS
-extern void svc_unregister __P((u_long, u_long));
+extern void svc_unreg __P((const rpcprog_t, const rpcvers_t));
__END_DECLS
/*
@@ -206,8 +234,6 @@ extern void xprt_unregister __P((SVCXPRT *));
__END_DECLS
-
-
/*
* When the service routine is called, it must first check to see if it
* knows about the procedure; if not, it should call svcerr_noproc
@@ -239,10 +265,13 @@ extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *));
extern void svcerr_decode __P((SVCXPRT *));
extern void svcerr_weakauth __P((SVCXPRT *));
extern void svcerr_noproc __P((SVCXPRT *));
-extern void svcerr_progvers __P((SVCXPRT *, u_long, u_long));
+extern void svcerr_progvers __P((SVCXPRT *, rpcvers_t, rpcvers_t));
extern void svcerr_auth __P((SVCXPRT *, enum auth_stat));
extern void svcerr_noprog __P((SVCXPRT *));
extern void svcerr_systemerr __P((SVCXPRT *));
+extern int rpc_reg __P((rpcprog_t, rpcvers_t, rpcproc_t,
+ char *(*) __P((char *)), xdrproc_t, xdrproc_t,
+ char *));
__END_DECLS
/*
@@ -261,64 +290,130 @@ __END_DECLS
* dynamic; must be inspected before each call to select
*/
extern int svc_maxfd;
+#ifdef FD_SETSIZE
extern fd_set svc_fdset;
#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
-#ifndef _KERNEL
/*
* a small program implemented by the svc_rpc implementation itself;
* also see clnt.h for protocol numbers.
*/
-extern void rpctest_service();
-#endif
+__BEGIN_DECLS
+extern void rpctest_service __P((void));
+__END_DECLS
__BEGIN_DECLS
extern void svc_getreq __P((int));
extern void svc_getreqset __P((fd_set *));
-extern void svc_getreqset2 __P((fd_set *, int)); /* XXX: nonstd, undoc */
+extern void svc_getreq_common __P((int));
+struct pollfd;
+extern void svc_getreq_poll __P((struct pollfd *, int));
+
extern void svc_run __P((void));
+extern void svc_exit __P((void));
__END_DECLS
/*
* Socket to use on svcxxx_create call to get default socket
*/
#define RPC_ANYSOCK -1
+#define RPC_ANYFD RPC_ANYSOCK
/*
* These are the existing service side transport implementations
*/
+__BEGIN_DECLS
/*
- * Memory based rpc for testing and timing.
+ * Transport independent svc_create routine.
+ */
+extern int svc_create __P((void (*) __P((struct svc_req *, SVCXPRT *)),
+ const rpcprog_t, const rpcvers_t, const char *));
+/*
+ * void (*dispatch)(); -- dispatch routine
+ * const rpcprog_t prognum; -- program number
+ * const rpcvers_t versnum; -- version number
+ * const char *nettype; -- network type
*/
-__BEGIN_DECLS
-extern SVCXPRT *svcraw_create __P((void));
-__END_DECLS
/*
- * Udp based rpc.
+ * Generic server creation routine. It takes a netconfig structure
+ * instead of a nettype.
*/
-__BEGIN_DECLS
-extern SVCXPRT *svcudp_create __P((int));
-extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int));
-__END_DECLS
+
+extern SVCXPRT *svc_tp_create __P((void (*) __P((struct svc_req *, SVCXPRT *)),
+ const rpcprog_t, const rpcvers_t,
+ const struct netconfig *));
+ /*
+ * void (*dispatch)(); -- dispatch routine
+ * const rpcprog_t prognum; -- program number
+ * const rpcvers_t versnum; -- version number
+ * const struct netconfig *nconf; -- netconfig structure
+ */
/*
- * Tcp based rpc.
+ * Generic TLI create routine
+ */
+extern SVCXPRT *svc_tli_create __P((const int, const struct netconfig *,
+ const struct t_bind *, const u_int,
+ const u_int));
+/*
+ * const int fd; -- connection end point
+ * const struct netconfig *nconf; -- netconfig structure for network
+ * const struct t_bind *bindaddr; -- local bind address
+ * const u_int sendsz; -- max sendsize
+ * const u_int recvsz; -- max recvsize
*/
-__BEGIN_DECLS
-extern SVCXPRT *svctcp_create __P((int, u_int, u_int));
-extern SVCXPRT *svcfd_create __P((int, u_int, u_int));
-__END_DECLS
/*
- * AF_UNIX socket based rpc.
+ * Connectionless and connectionful create routines
*/
-__BEGIN_DECLS
-extern SVCXPRT *svcunix_create __P((int, u_int, u_int, char *));
-extern SVCXPRT *svcunixfd_create __P((int, u_int, u_int));
+
+extern SVCXPRT *svc_vc_create __P((const int, const u_int, const u_int));
+/*
+ * const int fd; -- open connection end point
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+extern SVCXPRT *svc_dg_create __P((const int, const u_int, const u_int));
+ /*
+ * const int fd; -- open connection
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+
+/*
+ * the routine takes any *open* connection
+ * descriptor as its first input and is used for open connections.
+ */
+extern SVCXPRT *svc_fd_create __P((const int, const u_int, const u_int));
+/*
+ * const int fd; -- open connection end point
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ */
+extern SVCXPRT *svc_raw_create __P((void));
+
+/*
+ * svc_dg_enable_cache() enables the cache on dg transports.
+ */
+int svc_dg_enablecache __P((SVCXPRT *, const u_int));
+
__END_DECLS
+
+/* for backward compatibility */
+#include <rpc/svc_soc.h>
+
#endif /* !_RPC_SVC_H */
diff --git a/include/rpc/svc_auth.h b/include/rpc/svc_auth.h
index 536d6a6481c6..8f55339968e2 100644
--- a/include/rpc/svc_auth.h
+++ b/include/rpc/svc_auth.h
@@ -1,3 +1,5 @@
+/* $NetBSD: svc_auth.h,v 1.8 2000/06/02 22:57:57 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,7 +29,7 @@
* Mountain View, California 94043
*
* from: @(#)svc_auth.h 1.6 86/07/16 SMI
- * from: @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
+ * @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
*/
@@ -37,20 +39,17 @@
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
-#ifndef _RPC_SVCAUTH_H
-#define _RPC_SVCAUTH_H
-
-struct rpc_msg;
-struct svc_req;
+#ifndef _RPC_SVC_AUTH_H
+#define _RPC_SVC_AUTH_H
/*
* Server side authenticator
*/
__BEGIN_DECLS
extern enum auth_stat _authenticate __P((struct svc_req *, struct rpc_msg *));
-extern int svc_auth_reg __P((int, enum auth_stat (*)(struct svc_req *,
- struct rpc_msg *)));
-extern enum auth_stat _svcauth_des __P((struct svc_req *, struct rpc_msg *));
+extern int svc_auth_reg __P((int, enum auth_stat (*) __P((struct svc_req *,
+ struct rpc_msg *))));
+
__END_DECLS
-#endif /* !_RPC_SVCAUTH_H */
+#endif /* !_RPC_SVC_AUTH_H */
diff --git a/include/rpc/svc_dg.h b/include/rpc/svc_dg.h
new file mode 100644
index 000000000000..3514745d2efd
--- /dev/null
+++ b/include/rpc/svc_dg.h
@@ -0,0 +1,51 @@
+/* $NetBSD: svc_dg.h,v 1.1 2000/06/02 23:11:16 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * XXX - this file exists only so that the rpcbind code can pull it in.
+ * This should go away. It should only be include by svc_dg.c and
+ * rpcb_svc_com.c in the rpcbind code.
+ */
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svc_dg_data {
+ /* XXX: optbuf should be the first field, used by ti_opts.c code */
+ size_t su_iosz; /* size of send.recv buffer */
+ u_int32_t su_xid; /* transaction id */
+ XDR su_xdrs; /* XDR handle */
+ char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
+ void *su_cache; /* cached data, NULL if none */
+};
+
+#define __rpcb_get_dg_xidp(x) (&((struct svc_dg_data *)(x)->xp_p2)->su_xid)
diff --git a/include/rpc/svc_soc.h b/include/rpc/svc_soc.h
new file mode 100644
index 000000000000..c3d16fec6341
--- /dev/null
+++ b/include/rpc/svc_soc.h
@@ -0,0 +1,116 @@
+/* $NetBSD: svc_soc.h,v 1.1 2000/06/02 22:57:57 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ */
+
+#ifndef _RPC_SVC_SOC_H
+#define _RPC_SVC_SOC_H
+#include <sys/cdefs.h>
+
+/* #pragma ident "@(#)svc_soc.h 1.11 94/04/25 SMI" */
+/* svc_soc.h 1.8 89/05/01 SMI */
+
+/*
+ * All the following declarations are only for backward compatibility
+ * with TS-RPC
+ */
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * u_long prog;
+ * u_long vers;
+ * void (*dispatch)();
+ * int protocol; like TCP or UDP, zero means do not register
+ */
+__BEGIN_DECLS
+extern bool_t svc_register __P((SVCXPRT *, u_long, u_long,
+ void (*) __P((struct svc_req *, SVCXPRT *)), int));
+__END_DECLS
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern void svc_unregister __P((u_long, u_long));
+__END_DECLS
+
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcraw_create __P((void));
+__END_DECLS
+
+
+/*
+ * Udp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcudp_create __P((int));
+extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int));
+extern int svcudp_enablecache __P((SVCXPRT *, u_long));
+__END_DECLS
+
+
+/*
+ * Tcp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svctcp_create __P((int, u_int, u_int));
+__END_DECLS
+
+/*
+ * Fd based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcfd_create __P((int, u_int, u_int));
+__END_DECLS
+
+#endif /* !_RPC_SVC_SOC_H */
diff --git a/include/rpc/types.h b/include/rpc/types.h
index e2ceec5b3df7..4a5c6564b270 100644
--- a/include/rpc/types.h
+++ b/include/rpc/types.h
@@ -1,3 +1,5 @@
+/* $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -37,8 +39,18 @@
#ifndef _RPC_TYPES_H
#define _RPC_TYPES_H
-#define bool_t int32_t
-#define enum_t int32_t
+#include <sys/types.h>
+
+typedef int32_t bool_t;
+typedef int32_t enum_t;
+
+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;
+
#define __dontcare__ -1
#ifndef FALSE
@@ -51,12 +63,46 @@
# define NULL 0
#endif
-#define mem_alloc(bsize) malloc(bsize)
+#define mem_alloc(bsize) calloc(1, bsize)
#define mem_free(ptr, bsize) free(ptr)
-#ifndef makedev /* ie, we haven't already included it */
-#include <sys/types.h>
-#endif
#include <sys/time.h>
+#include <netconfig.h>
+
+/*
+ * The netbuf structure is defined here, because FreeBSD / NetBSD only use
+ * it inside the RPC code. It's in <xti.h> on SVR4, but it would be confusing
+ * to have an xti.h, since FreeBSD / NetBSD does not support XTI/TLI.
+ */
+
+/*
+ * The netbuf structure is used for transport-independent address storage.
+ */
+struct netbuf {
+ unsigned int maxlen;
+ unsigned int len;
+ void *buf;
+};
+
+/*
+ * The format of the addres and options arguments of the XTI t_bind call.
+ * Only provided for compatibility, it should not be used.
+ */
+
+struct t_bind {
+ struct netbuf addr;
+ unsigned int qlen;
+};
+
+/*
+ * Internal library and rpcbind use. This is not an exported interface, do
+ * not use.
+ */
+struct __rpc_sockinfo {
+ int si_af;
+ int si_proto;
+ int si_socktype;
+ int si_alen;
+};
#endif /* !_RPC_TYPES_H */
diff --git a/include/rpc/xdr.h b/include/rpc/xdr.h
index 2ce9205422e6..90107ffc92ac 100644
--- a/include/rpc/xdr.h
+++ b/include/rpc/xdr.h
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -97,15 +99,15 @@ enum xdr_op {
*/
typedef struct __rpc_xdr {
enum xdr_op x_op; /* operation; fast additional param */
- struct xdr_ops {
+ const struct xdr_ops {
/* get a long from underlying stream */
bool_t (*x_getlong) __P((struct __rpc_xdr *, long *));
- /* put a long to underlying stream */
- bool_t (*x_putlong) __P((struct __rpc_xdr *, long *));
- /* get some bytes from underlying stream */
- bool_t (*x_getbytes) __P((struct __rpc_xdr *, caddr_t, u_int));
- /* put some bytes to underlying stream */
- bool_t (*x_putbytes) __P((struct __rpc_xdr *, caddr_t, u_int));
+ /* put a long to " */
+ bool_t (*x_putlong) __P((struct __rpc_xdr *, const long *));
+ /* get some bytes from " */
+ bool_t (*x_getbytes) __P((struct __rpc_xdr *, char *, u_int));
+ /* put some bytes to " */
+ bool_t (*x_putbytes) __P((struct __rpc_xdr *, const char *, u_int));
/* returns bytes off from beginning */
u_int (*x_getpostn) __P((struct __rpc_xdr *));
/* lets you reposition the stream */
@@ -114,10 +116,11 @@ typedef struct __rpc_xdr {
int32_t *(*x_inline) __P((struct __rpc_xdr *, u_int));
/* free privates of this xdr_stream */
void (*x_destroy) __P((struct __rpc_xdr *));
+ bool_t (*x_control) __P((struct __rpc_xdr *, int, void *));
} *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 */
+ char * x_public; /* users' data */
+ void * x_private; /* pointer to private data */
+ char * x_base; /* private used for position info */
int x_handy; /* extra private word */
} XDR;
@@ -128,22 +131,17 @@ typedef struct __rpc_xdr {
* The opaque pointer generally points to a structure of the data type
* to be decoded. If this pointer is 0, then the type routines should
* allocate dynamic storage of the appropriate size and return it.
- */
-#ifdef _KERNEL
-typedef bool_t (*xdrproc_t) __P((XDR *, void *, u_int));
-#else
-/*
- * XXX can't actually prototype it, because some take two args!!!
+ *
+ * XXX can't actually prototype it, because some take three args!!!
*/
typedef bool_t (*xdrproc_t) __P((/* XDR *, void *, u_int */));
-#endif
/*
* Operations defined on a XDR handle
*
* XDR *xdrs;
* long *longp;
- * caddr_t addr;
+ * char * addr;
* u_int len;
* u_int pos;
*/
@@ -157,6 +155,29 @@ typedef bool_t (*xdrproc_t) __P((/* XDR *, void *, u_int */));
#define xdr_putlong(xdrs, longp) \
(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+static __inline int
+xdr_getint32(XDR *xdrs, int32_t *ip)
+{
+ long l;
+
+ if (!xdr_getlong(xdrs, &l))
+ return (FALSE);
+ *ip = (int32_t)l;
+ return (TRUE);
+}
+
+static __inline int
+xdr_putint32(XDR *xdrs, int32_t *ip)
+{
+ long l;
+
+ l = (long)*ip;
+ return xdr_putlong(xdrs, &l);
+}
+
+#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p)
+#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p)
+
#define XDR_GETBYTES(xdrs, addr, len) \
(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
#define xdr_getbytes(xdrs, addr, len) \
@@ -189,6 +210,21 @@ typedef bool_t (*xdrproc_t) __P((/* XDR *, void *, u_int */));
if ((xdrs)->x_ops->x_destroy) \
(*(xdrs)->x_ops->x_destroy)(xdrs)
+#define XDR_CONTROL(xdrs, req, op) \
+ if ((xdrs)->x_ops->x_control) \
+ (*(xdrs)->x_ops->x_control)(xdrs, req, op)
+#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op)
+
+/*
+ * Solaris strips the '_t' from these types -- not sure why.
+ * But, let's be compatible.
+ */
+#define xdr_rpcvers(xdrs, versp) xdr_u_int32(xdrs, versp)
+#define xdr_rpcprog(xdrs, progp) xdr_u_int32(xdrs, progp)
+#define xdr_rpcproc(xdrs, procp) xdr_u_int32(xdrs, procp)
+#define xdr_rpcprot(xdrs, protp) xdr_u_int32(xdrs, protp)
+#define xdr_rpcport(xdrs, portp) xdr_u_int32(xdrs, portp)
+
/*
* Support struct for discriminated unions.
* You create an array of xdrdiscrim structures, terminated with
@@ -220,8 +256,13 @@ struct xdr_discrim {
* N.B. and frozen for all time: each data type here uses 4 bytes
* of external representation.
*/
-#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++))
-#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v))
+#define IXDR_GET_INT32(buf) ((int32_t)ntohl((u_int32_t)*(buf)++))
+#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v))
+#define IXDR_GET_U_INT32(buf) ((u_int32_t)IXDR_GET_INT32(buf))
+#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))
+
+#define IXDR_GET_LONG(buf) ((long)ntohl((u_int32_t)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v))
#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
@@ -229,11 +270,11 @@ struct xdr_discrim {
#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))
-#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
-#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
-#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
-#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
-#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))
/*
* These are the "generic" xdr routines.
@@ -256,19 +297,23 @@ extern bool_t xdr_bool __P((XDR *, bool_t *));
extern bool_t xdr_enum __P((XDR *, enum_t *));
extern bool_t xdr_array __P((XDR *, char **, u_int *, u_int, u_int, xdrproc_t));
extern bool_t xdr_bytes __P((XDR *, char **, u_int *, u_int));
-extern bool_t xdr_opaque __P((XDR *, caddr_t, u_int));
+extern bool_t xdr_opaque __P((XDR *, char *, u_int));
extern bool_t xdr_string __P((XDR *, char **, u_int));
-extern bool_t xdr_union __P((XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t));
-extern unsigned long xdr_sizeof __P((xdrproc_t, void *));
+extern bool_t xdr_union __P((XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t));
extern bool_t xdr_char __P((XDR *, char *));
extern bool_t xdr_u_char __P((XDR *, u_char *));
extern bool_t xdr_vector __P((XDR *, char *, u_int, u_int, xdrproc_t));
extern bool_t xdr_float __P((XDR *, float *));
extern bool_t xdr_double __P((XDR *, double *));
-extern bool_t xdr_reference __P((XDR *, caddr_t *, u_int, xdrproc_t));
-extern bool_t xdr_pointer __P((XDR *, caddr_t *, u_int, xdrproc_t));
+extern bool_t xdr_quadruple __P((XDR *, long double *));
+extern bool_t xdr_reference __P((XDR *, char **, u_int, xdrproc_t));
+extern bool_t xdr_pointer __P((XDR *, char **, u_int, xdrproc_t));
extern bool_t xdr_wrapstring __P((XDR *, char **));
extern void xdr_free __P((xdrproc_t, char *));
+extern bool_t xdr_hyper __P((XDR *, quad_t *));
+extern bool_t xdr_u_hyper __P((XDR *, u_quad_t *));
+extern bool_t xdr_longlong_t __P((XDR *, quad_t *));
+extern bool_t xdr_u_longlong_t __P((XDR *, u_quad_t *));
__END_DECLS
/*
@@ -291,15 +336,15 @@ __BEGIN_DECLS
/* XDR using memory buffers */
extern void xdrmem_create __P((XDR *, char *, u_int, enum xdr_op));
-#ifdef _STDIO_H_
/* XDR using stdio library */
+#ifdef _STDIO_H_
extern void xdrstdio_create __P((XDR *, FILE *, enum xdr_op));
#endif
/* XDR pseudo records for tcp */
extern void xdrrec_create __P((XDR *, u_int, u_int, char *,
- int (*) __P((caddr_t, caddr_t, int)),
- int (*) __P((caddr_t, caddr_t, int))));
+ int (*) __P((char *, char *, int)),
+ int (*) __P((char *, char *, int))));
/* make end of xdr record */
extern bool_t xdrrec_endofrecord __P((XDR *, int));
@@ -309,6 +354,7 @@ extern bool_t xdrrec_skiprecord __P((XDR *));
/* true if no more input */
extern bool_t xdrrec_eof __P((XDR *));
+extern u_int xdrrec_readbytes __P((XDR *, caddr_t, u_int));
__END_DECLS
#endif /* !_RPC_XDR_H */
diff --git a/include/rpcsvc/key_prot.x b/include/rpcsvc/key_prot.x
index ab3196cfc04c..d87f39ccb910 100644
--- a/include/rpcsvc/key_prot.x
+++ b/include/rpcsvc/key_prot.x
@@ -44,7 +44,7 @@
*/
%/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */
-%
+%/* $FreeBSD$ */
%/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
%
%/*
diff --git a/include/rpcsvc/nlm_prot.x b/include/rpcsvc/nlm_prot.x
index 4c3ea7d8e8ec..ba0ccf33c6cf 100644
--- a/include/rpcsvc/nlm_prot.x
+++ b/include/rpcsvc/nlm_prot.x
@@ -1,6 +1,3 @@
-/* @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC */
-/* @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro */
-
/*
* Network lock manager protocol definition
* Copyright (C) 1986 Sun Microsystems, Inc.
@@ -12,9 +9,13 @@
%#define LM_MAXSTRLEN 1024
%#define MAXNAMELEN LM_MAXSTRLEN+1
#else
+%#include <sys/cdefs.h>
%#ifndef lint
%static const char rcsid[] =
% "$FreeBSD$";
+%/*static char sccsid[] = "from: @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
+%__RCSID("$NetBSD: nlm_prot.x,v 1.6 2000/06/07 14:30:15 bouyer Exp $");
%#endif /* not lint */
#endif
@@ -77,20 +78,20 @@ struct nlm_lockargs {
};
struct nlm_cancargs {
- netobj cookie;
+ netobj cookie;
bool block;
bool exclusive;
struct nlm_lock alock;
};
struct nlm_testargs {
- netobj cookie;
+ netobj cookie;
bool exclusive;
struct nlm_lock alock;
};
struct nlm_unlockargs {
- netobj cookie;
+ netobj cookie;
struct nlm_lock alock;
};
@@ -140,11 +141,127 @@ struct nlm_notify {
long state;
};
+#ifdef RPC_HDR
+%/* definitions for NLM version 4 */
+#endif
+enum nlm4_stats {
+ nlm4_granted = 0,
+ nlm4_denied = 1,
+ nlm4_denied_nolock = 2,
+ nlm4_blocked = 3,
+ nlm4_denied_grace_period = 4,
+ nlm4_deadlck = 5,
+ nlm4_rofs = 6,
+ nlm4_stale_fh = 7,
+ nlm4_fbig = 8,
+ nlm4_failed = 9
+};
+
+struct nlm4_stat {
+ nlm4_stats stat;
+};
+
+struct nlm4_holder {
+ bool exclusive;
+ u_int32_t svid;
+ netobj oh;
+ u_int64_t l_offset;
+ u_int64_t l_len;
+};
+
+struct nlm4_lock {
+ string caller_name<MAXNAMELEN>;
+ netobj fh;
+ netobj oh;
+ u_int32_t svid;
+ u_int64_t l_offset;
+ u_int64_t l_len;
+};
+
+struct nlm4_share {
+ string caller_name<MAXNAMELEN>;
+ netobj fh;
+ netobj oh;
+ fsh_mode mode;
+ fsh_access access;
+};
+
+union nlm4_testrply switch (nlm4_stats stat) {
+ case nlm_denied:
+ struct nlm4_holder holder;
+ default:
+ void;
+};
+
+struct nlm4_testres {
+ netobj cookie;
+ nlm4_testrply stat;
+};
+
+struct nlm4_testargs {
+ netobj cookie;
+ bool exclusive;
+ struct nlm4_lock alock;
+};
+
+struct nlm4_res {
+ netobj cookie;
+ nlm4_stat stat;
+};
+
+struct nlm4_lockargs {
+ netobj cookie;
+ bool block;
+ bool exclusive;
+ struct nlm4_lock alock;
+ bool reclaim; /* used for recovering locks */
+ int state; /* specify local status monitor state */
+};
+
+struct nlm4_cancargs {
+ netobj cookie;
+ bool block;
+ bool exclusive;
+ struct nlm4_lock alock;
+};
+
+struct nlm4_unlockargs {
+ netobj cookie;
+ struct nlm4_lock alock;
+};
+
+struct nlm4_shareargs {
+ netobj cookie;
+ nlm4_share share;
+ bool reclaim;
+};
+
+struct nlm4_shareres {
+ netobj cookie;
+ nlm4_stats stat;
+ int sequence;
+};
+
+/*
+ * argument for the procedure called by rpc.statd when a monitored host
+ * status change.
+ * XXX assumes LM_MAXSTRLEN == SM_MAXSTRLEN
+ */
+struct nlm_sm_status {
+ string mon_name<LM_MAXSTRLEN>; /* name of host */
+ int state; /* new state */
+ opaque priv[16]; /* private data */
+};
+
/*
* Over-the-wire protocol used between the network lock managers
*/
program NLM_PROG {
+ version NLM_SM {
+ void NLM_SM_NOTIFY(struct nlm_sm_status) = 1;
+ } = 0;
+
version NLM_VERS {
nlm_testres NLM_TEST(struct nlm_testargs) = 1;
@@ -180,5 +297,25 @@ program NLM_PROG {
void NLM_FREE_ALL(nlm_notify) = 23;
} = 3;
+ version NLM_VERS4 {
+ nlm4_testres NLM4_TEST(nlm4_testargs) = 1;
+ nlm4_res NLM4_LOCK(nlm4_lockargs) = 2;
+ nlm4_res NLM4_CANCEL(nlm4_cancargs) = 3;
+ nlm4_res NLM4_UNLOCK(nlm4_unlockargs) = 4;
+ nlm4_res NLM4_GRANTED(nlm4_testargs) = 5;
+ void NLM4_TEST_MSG(nlm4_testargs) = 6;
+ void NLM4_LOCK_MSG(nlm4_lockargs) = 7;
+ void NLM4_CANCEL_MSG(nlm4_cancargs) = 8;
+ void NLM4_UNLOCK_MSG(nlm4_unlockargs) = 9;
+ void NLM4_GRANTED_MSG(nlm4_testargs) = 10;
+ void NLM4_TEST_RES(nlm4_testres) = 11;
+ void NLM4_LOCK_RES(nlm4_res) = 12;
+ void NLM4_CANCEL_RES(nlm4_res) = 13;
+ void NLM4_UNLOCK_RES(nlm4_res) = 14;
+ void NLM4_GRANTED_RES(nlm4_res) = 15;
+ nlm4_shareres NLM4_SHARE(nlm4_shareargs) = 20;
+ nlm4_shareres NLM4_UNSHARE(nlm4_shareargs) = 21;
+ nlm4_res NLM4_NM_LOCK(nlm4_lockargs) = 22;
+ void NLM4_FREE_ALL(nlm_notify) = 23;
+ } = 4;
} = 100021;
-
diff --git a/include/rpcsvc/sm_inter.x b/include/rpcsvc/sm_inter.x
index f5bf54524110..6e1862bf9fc5 100644
--- a/include/rpcsvc/sm_inter.x
+++ b/include/rpcsvc/sm_inter.x
@@ -62,6 +62,7 @@ program SM_PROG {
struct sm_stat SM_UNMON_ALL(struct my_id) = 4;
void SM_SIMU_CRASH(void) = 5;
+ void SM_NOTIFY(struct stat_chge) = 6;
} = 1;
} = 100024;
@@ -90,6 +91,10 @@ struct mon{
opaque priv[16]; /* private information to store at monitor for requesting process */
};
+struct stat_chge {
+ string mon_name<SM_MAXSTRLEN>; /* name of the site that had the state change */
+ int state;
+};
/*
* state # of status monitor monitonically increases each time
diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c
index be6dab74635c..478335902297 100644
--- a/lib/libc/gen/_pthread_stubs.c
+++ b/lib/libc/gen/_pthread_stubs.c
@@ -26,7 +26,9 @@
* $FreeBSD$
*/
+#include <signal.h>
#include <pthread.h>
+#include <pthread_np.h>
/*
* Weak symbols: All libc internal usage of these functions should
@@ -37,9 +39,13 @@
* between application locks and libc locks (threads holding the
* latter can't be allowed to exit/terminate).
*/
+#pragma weak _pthread_cond_init=_pthread_cond_init_stub
+#pragma weak _pthread_cond_signal=_pthread_cond_signal_stub
+#pragma weak _pthread_cond_wait=_pthread_cond_wait_stub
#pragma weak _pthread_getspecific=_pthread_getspecific_stub
#pragma weak _pthread_key_create=_pthread_key_create_stub
#pragma weak _pthread_key_delete=_pthread_key_delete_stub
+#pragma weak _pthread_main_np=_pthread_main_np_stub
#pragma weak _pthread_mutex_destroy=_pthread_mutex_destroy_stub
#pragma weak _pthread_mutex_init=_pthread_mutex_init_stub
#pragma weak _pthread_mutex_lock=_pthread_mutex_lock_stub
@@ -50,13 +56,40 @@
#pragma weak _pthread_mutexattr_settype=_pthread_mutexattr_settype_stub
#pragma weak _pthread_once=_pthread_once_stub
#pragma weak _pthread_self=_pthread_self_stub
+#pragma weak _pthread_rwlock_init=_pthread_rwlock_init_stub
+#pragma weak _pthread_rwlock_rdlock=_pthread_rwlock_rdlock_stub
+#pragma weak _pthread_rwlock_tryrdlock=_pthread_rwlock_tryrdlock_stub
+#pragma weak _pthread_rwlock_trywrloc=_pthread_rwlock_trywrlock_stub
+#pragma weak _pthread_rwlock_unlock=_pthread_rwlock_unlock_stub
+#pragma weak _pthread_rwlock_wrlock=_pthread_rwlock_wrlock_stub
#pragma weak _pthread_setspecific=_pthread_setspecific_stub
+#pragma weak _pthread_sigmask=_pthread_sigmask_stub
+/* Define a null pthread structure just to satisfy _pthread_self. */
struct pthread {
};
static struct pthread main_thread;
+int
+_pthread_cond_init_stub(pthread_cond_t *cond,
+ const pthread_condattr_t *cond_attr)
+{
+ return (0);
+}
+
+int
+_pthread_cond_signal_stub(pthread_cond_t *cond)
+{
+ return (0);
+}
+
+int
+_pthread_cond_wait_stub(pthread_cond_t *cond,
+ pthread_mutex_t *mutex)
+{
+ return (0);
+}
void *
_pthread_getspecific_stub(pthread_key_t key)
@@ -77,6 +110,12 @@ _pthread_key_delete_stub(pthread_key_t key)
}
int
+_pthread_main_np_stub()
+{
+ return (-1);
+}
+
+int
_pthread_mutex_destroy_stub(pthread_mutex_t *mattr)
{
return (0);
@@ -130,6 +169,49 @@ _pthread_once_stub(pthread_once_t *once_control, void (*init_routine) (void))
return (0);
}
+int
+_pthread_rwlock_init_stub(pthread_rwlock_t *rwlock,
+ const pthread_rwlockattr_t *attr)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_destroy_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_rdlock_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_tryrdlock_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_trywrlock_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_unlock_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
+int
+_pthread_rwlock_wrlock_stub(pthread_rwlock_t *rwlock)
+{
+ return (0);
+}
+
pthread_t
_pthread_self_stub(void)
{
@@ -141,3 +223,14 @@ _pthread_setspecific_stub(pthread_key_t key, const void *value)
{
return (0);
}
+
+int
+_pthread_sigmask_stub(int how, const sigset_t *set, sigset_t *oset)
+{
+ /*
+ * No need to use _sigprocmask, since we know that the threads
+ * library is not linked in.
+ *
+ */
+ return (sigprocmask(how, set, oset));
+}
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index ddffa82e4025..cc15a692d987 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -58,9 +58,15 @@
#define listen _listen
#define nanosleep _nanosleep
#define open _open
+#define poll _poll
+#define pthread_cond_signal _pthread_cond_signal
+#define pthread_cond_wait _pthread_cond_wait
+#define pthread_cond_init _pthread_cond_init
+#define pthread_exit _pthread_exit
#define pthread_getspecific _pthread_getspecific
#define pthread_key_create _pthread_key_create
#define pthread_key_delete _pthread_key_delete
+#define pthread_main_np _pthread_main_np
#define pthread_mutex_destroy _pthread_mutex_destroy
#define pthread_mutex_init _pthread_mutex_init
#define pthread_mutex_lock _pthread_mutex_lock
@@ -70,8 +76,13 @@
#define pthread_mutexattr_destroy _pthread_mutexattr_destroy
#define pthread_mutexattr_settype _pthread_mutexattr_settype
#define pthread_once _pthread_once
+#define pthread_rwlock_init _pthread_rwlock_init
+#define pthread_rwlock_rdlock _pthread_rwlock_rdlock
+#define pthread_rwlock_wrlock _pthread_rwlock_wrlock
+#define pthread_rwlock_unlock _pthread_rwlock_unlock
#define pthread_self _pthread_self
#define pthread_setspecific _pthread_setspecific
+#define pthread_sigmask _pthread_sigmask
#define read _read
#define readv _readv
#define recvfrom _recvfrom
@@ -106,14 +117,9 @@
#define msync _msync
#define nfssvc _nfssvc
#define pause _pause
-#define poll _poll
#define pthread_rwlock_destroy _pthread_rwlock_destroy
-#define pthread_rwlock_init _pthread_rwlock_init
-#define pthread_rwlock_rdlock _pthread_rwlock_rdlock
#define pthread_rwlock_tryrdlock _pthread_rwlock_tryrdlock
#define pthread_rwlock_trywrlock _pthread_rwlock_trywrlock
-#define pthread_rwlock_unlock _pthread_rwlock_unlock
-#define pthread_rwlock_wrlock _pthread_rwlock_wrlock
#define pthread_rwlockattr_init _pthread_rwlockattr_init
#define pthread_rwlockattr_destroy _pthread_rwlockattr_destroy
#define sched_yield _sched_yield
diff --git a/lib/libc/include/reentrant.h b/lib/libc/include/reentrant.h
new file mode 100644
index 000000000000..e6ceb5ba1413
--- /dev/null
+++ b/lib/libc/include/reentrant.h
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 1997,98 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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 the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Requirements:
+ *
+ * 1. The thread safe mechanism should be lightweight so the library can
+ * be used by non-threaded applications without unreasonable overhead.
+ *
+ * 2. There should be no dependency on a thread engine for non-threaded
+ * applications.
+ *
+ * 3. There should be no dependency on any particular thread engine.
+ *
+ * 4. The library should be able to be compiled without support for thread
+ * safety.
+ *
+ *
+ * Rationale:
+ *
+ * One approach for thread safety is to provide discrete versions of the
+ * library: one thread safe, the other not. The disadvantage of this is
+ * that libc is rather large, and two copies of a library which are 99%+
+ * identical is not an efficent use of resources.
+ *
+ * Another approach is to provide a single thread safe library. However,
+ * it should not add significant run time or code size overhead to non-
+ * threaded applications.
+ *
+ * Since the NetBSD C library is used in other projects, it should be
+ * easy to replace the mutual exclusion primitives with ones provided by
+ * another system. Similarly, it should also be easy to remove all
+ * support for thread safety completely if the target environment does
+ * not support threads.
+ *
+ *
+ * Implementation Details:
+ *
+ * The mutex primitives used by the library (mutex_t, mutex_lock, etc.)
+ * are macros which expand to the cooresponding primitives provided by
+ * the thread engine or to nothing. The latter is used so that code is
+ * not unreasonably cluttered with #ifdefs when all thread safe support
+ * is removed.
+ *
+ * The mutex macros can be directly mapped to the mutex primitives from
+ * pthreads, however it should be reasonably easy to wrap another mutex
+ * implementation so it presents a similar interface.
+ *
+ * Stub implementations of the mutex functions are provided with *weak*
+ * linkage. These functions simply return success. When linked with a
+ * thread library (i.e. -lpthread), the functions will override the
+ * stubs.
+ */
+
+#include <pthread.h>
+#include <pthread_np.h>
+#include "libc_private.h"
+
+#define mutex_t pthread_mutex_t
+#define cond_t pthread_cond_t
+#define rwlock_t pthread_rwlock_t
+
+#define thread_key_t pthread_key_t
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+
+#define mutex_init(m, a) _pthread_mutex_init(m, a)
+#define mutex_lock(m) if (__isthreaded) \
+ _pthread_mutex_lock(m)
+#define mutex_unlock(m) if (__isthreaded) \
+ _pthread_mutex_unlock(m)
+#define mutex_trylock(m) (__isthreaded ? 0 : _pthread_mutex_trylock(m))
+
+#define cond_init(c, a, p) _pthread_cond_init(c, a)
+#define cond_signal(m) if (__isthreaded) \
+ _pthread_cond_signal(m)
+#define cond_wait(c, m) if (__isthreaded) \
+ _pthread_cond_wait(c, m)
+
+#define rwlock_init(l, a) _pthread_rwlock_init(l, a)
+#define rwlock_rdlock(l) if (__isthreaded) \
+ _pthread_rwlock_rdlock(l)
+#define rwlock_wrlock(l) if (__isthreaded) \
+ _pthread_rwlock_wrlock(l)
+#define rwlock_unlock(l) if (__isthreaded) \
+ _pthread_rwlock_unlock(l)
+
+#define thr_keycreate(k, d) _pthread_key_create(k, d)
+#define thr_setspecific(k, p) _pthread_setspecific(k, p)
+#define thr_getspecific(k) _pthread_getspecific(k)
+#define thr_sigsetmask(f, n, o) _pthread_sigmask(f, n, o)
+
+#define thr_self() _pthread_self()
+#define thr_exit(x) _pthread_exit(x)
+#define thr_main() _pthread_main_np()
diff --git a/lib/libc/rpc/DISCLAIMER b/lib/libc/rpc/DISCLAIMER
index 1a66d5f4c9cd..9a3a99161ae8 100644
--- a/lib/libc/rpc/DISCLAIMER
+++ b/lib/libc/rpc/DISCLAIMER
@@ -1,3 +1,6 @@
+/* $NetBSD: DISCLAIMER,v 1.2 1998/01/09 04:11:51 perry Exp $ */
+/* $FreeBSD$ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc
index f9471598931e..1247c808a657 100644
--- a/lib/libc/rpc/Makefile.inc
+++ b/lib/libc/rpc/Makefile.inc
@@ -1,25 +1,35 @@
-# @(#)Makefile 5.11 (Berkeley) 9/6/90
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
# $FreeBSD$
.PATH: ${.CURDIR}/../libc/rpc ${.CURDIR}/.
+SRCS+= 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
-SRCS+= auth_des.c auth_none.c auth_time.c auth_unix.c \
- authdes_prot.c authunix_prot.c bindresvport.c \
- clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
- clnt_udp.c clnt_unix.c crypt_client.c des_crypt.c des_soft.c \
- get_myaddress.c getpublickey.c getrpcent.c getrpcport.c \
- key_call.c key_prot_xdr.c netname.c netnamer.c \
- pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
- pmap_prot2.c pmap_rmt.c rpc_callmsg.c rpc_commondata.c \
- rpc_dtablesize.c rpc_prot.c rpcdname.c rtime.c \
- svc.c svc_auth.c svc_auth_des.c svc_auth_unix.c \
- svc_raw.c svc_run.c svc_simple.c \
- svc_tcp.c svc_udp.c svc_unix.c
+# XDR
+SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \
+ xdr_stdio.c
+
+# Secure-RPC
+SRCS+= auth_time.c auth_des.c authdes_prot.c des_crypt.c des_soft.c \
+ crypt_client.c key_call.c key_prot_xdr.c getpublickey.c \
+ svc_auth_des.c
+
+# Resolver stuff
+SRCS+= netname.c netnamer.c rpcdname.c
+
+# Misc Source
+SRCS+= rtime.c
# generated sources
-SRCS+= crypt_clnt.c crypt_xdr.c crypt.h
+SRCS+= crypt_clnt.c crypt_xdr.c crypt.h
-CFLAGS+= -DBROKEN_DES
+CFLAGS+= -DBROKEN_DES -DPORTMAP -DDES_BUILTIN
CLEANFILES+= crypt_clnt.c crypt_xdr.c crypt.h
@@ -34,79 +44,113 @@ crypt_xdr.c: ${RPCDIR}/crypt.x crypt.h
crypt.h: ${RPCDIR}/crypt.x
${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/crypt.x
-
-.if ${LIB} == "c"
-
-MAN3+= bindresvport.3 des_crypt.3 getrpcent.3 getrpcport.3 publickey.3 rpc.3 \
- rpc_secure.3 rtime.3
-MAN5+= publickey.5 rpc.5
-
+MAN3+= bindresvport.3 des_crypt.3 getnetconfig.3 getnetpath.3 getrpcent.3 \
+ getrpcport.3 rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 \
+ rpc_clnt_create.3 rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 \
+ rpc_svc_reg.3 rpc_xdr.3 rpcbind.3 xdr.3 publickey.3 rpc_secure.3 \
+ rtime.3
+MAN5+= publickey.5 rpc.5 netconfig.5
MLINKS+= bindresvport.3 bindresvport_sa.3 \
- getrpcent.3 endrpcent.3 \
+ getnetconfig.3 setnetconfig.3 \
+ getnetconfig.3 getnetconfigent.3 \
+ getnetconfig.3 endnetconfig.3 \
+ getnetconfig.3 nc_perror.3 \
+ getnetconfig.3 nc_sperror.3 \
+ getnetpath.3 setnetpath.3 \
+ getnetpath.3 endnetpath.3 \
getrpcent.3 getrpcbyname.3 \
getrpcent.3 getrpcbynumber.3 \
+ getrpcent.3 endrpcent.3 \
getrpcent.3 setrpcent.3 \
- rpc.3 auth_destroy.3 \
- rpc.3 authnone_create.3 \
- rpc.3 authunix_create.3 \
- rpc.3 authunix_create_default.3 \
- rpc.3 callrpc.3 \
- rpc.3 clnt_broadcast.3 \
- rpc.3 clnt_call.3 \
- rpc.3 clnt_control.3 \
- rpc.3 clnt_create.3 \
- rpc.3 clnt_destroy.3 \
- rpc.3 clnt_freeres.3 \
- rpc.3 clnt_geterr.3 \
- rpc.3 clnt_pcreateerror.3 \
- rpc.3 clnt_perrno.3 \
- rpc.3 clnt_perror.3 \
- rpc.3 clnt_spcreateerror.3 \
- rpc.3 clnt_sperrno.3 \
- rpc.3 clnt_sperror.3 \
- rpc.3 clntraw_create.3 \
- rpc.3 clnttcp_create.3 \
- rpc.3 clntudp_bufcreate.3 \
- rpc.3 clntudp_create.3 \
- rpc.3 get_myaddress.3 \
- rpc.3 pmap_getmaps.3 \
- rpc.3 pmap_getport.3 \
- rpc.3 pmap_rmtcall.3 \
- rpc.3 pmap_set.3 \
- rpc.3 pmap_unset.3 \
- rpc.3 regsterrpc.3 \
- rpc.3 rpc_createerr.3 \
- rpc.3 svc_destroy.3 \
- rpc.3 svc_fds.3 \
- rpc.3 svc_fdset.3 \
- rpc.3 svc_getargs.3 \
- rpc.3 svc_getcaller.3 \
- rpc.3 svc_getreg.3 \
- rpc.3 svc_getregset.3 \
- rpc.3 svc_register.3 \
- rpc.3 svc_run.3 \
- rpc.3 svc_sendreply.3 \
- rpc.3 svc_unregister.3 \
- rpc.3 svcerr_auth.3 \
- rpc.3 svcerr_decode.3 \
- rpc.3 svcerr_noproc.3 \
- rpc.3 svcerr_noprog.3 \
- rpc.3 svcerr_progvers.3 \
- rpc.3 svcerr_systemerr.3 \
- rpc.3 svcerr_weakauth.3 \
- rpc.3 svcfd_create.3 \
- rpc.3 svcraw_create.3 \
- rpc.3 svctcp_create.3 \
- rpc.3 svcudp_bufcreate.3 \
- rpc.3 xdr_accepted_reply.3 \
- rpc.3 xdr_authunix_parms.3 \
- rpc.3 xdr_callhdr.3 \
- rpc.3 xdr_callmsg.3 \
- rpc.3 xdr_opaque_auth.3 \
- rpc.3 xdr_pmap.3 \
- rpc.3 xdr_pmaplist.3 \
- rpc.3 xdr_rejected_reply.3 \
- rpc.3 xdr_replymsg.3 \
- rpc.3 xprt_register.3 \
- rpc.3 xprt_unregister.3
-.endif
+ rpc_clnt_auth.3 auth_destroy.3 \
+ rpc_clnt_auth.3 authnone_create.3 \
+ rpc_clnt_auth.3 authsys_create.3 \
+ rpc_clnt_auth.3 authsys_create_default.3 \
+ rpc_clnt_calls.3 clnt_call.3 \
+ rpc_clnt_calls.3 clnt_perrno.3 \
+ rpc_clnt_calls.3 clnt_perror.3 \
+ rpc_clnt_calls.3 clnt_sperrno.3 \
+ rpc_clnt_calls.3 clnt_sperror.3 \
+ rpc_clnt_calls.3 rpc_call.3 \
+ rpc_clnt_calls.3 rpc_broadcast.3 \
+ rpc_clnt_calls.3 rpc_broadcast_exp.3 \
+ rpc_clnt_calls.3 clnt_freeres.3 \
+ rpc_clnt_calls.3 clnt_geterr.3 \
+ rpc_clnt_create.3 clnt_control.3 \
+ rpc_clnt_create.3 clnt_create.3 \
+ rpc_clnt_create.3 clnt_create_vers.3 \
+ rpc_clnt_create.3 clnt_destroy.3 \
+ rpc_clnt_create.3 clnt_pcreateerror.3 \
+ rpc_clnt_create.3 clnt_spcreateerror.3 \
+ rpc_clnt_create.3 clnt_dg_create.3 \
+ rpc_clnt_create.3 clnt_raw_create.3 \
+ rpc_clnt_create.3 clnt_tli_create.3 \
+ rpc_clnt_create.3 clnt_tp_create.3 \
+ rpc_clnt_create.3 clnt_vc_create.3 \
+ rpc_svc_calls.3 svc_dg_enablecache.3 \
+ rpc_svc_calls.3 svc_exit.3 \
+ rpc_svc_calls.3 svc_freeargs.3 \
+ rpc_svc_calls.3 svc_getargs.3 \
+ rpc_svc_calls.3 svc_getreq_common.3 \
+ rpc_svc_calls.3 svc_getreq_poll.3 \
+ rpc_svc_calls.3 svc_getreqset.3 \
+ rpc_svc_calls.3 svc_getrpccaller.3 \
+ rpc_svc_calls.3 __svc_getcallercreds.3 \
+ rpc_svc_calls.3 svc_pollset.3 \
+ rpc_svc_calls.3 svc_run.3 \
+ rpc_svc_calls.3 svc_sendreply.3 \
+ rpc_svc_create.3 svc_control.3 \
+ rpc_svc_create.3 svc_create.3 \
+ rpc_svc_create.3 svc_dg_create.3 \
+ rpc_svc_create.3 svc_destroy.3 \
+ rpc_svc_create.3 svc_fd_create.3 \
+ rpc_svc_create.3 svc_raw_create.3 \
+ rpc_svc_create.3 svc_tli_create.3 \
+ rpc_svc_create.3 svc_tp_create.3 \
+ rpc_svc_create.3 svc_vc_create.3 \
+ rpc_svc_err.3 svcerr_auth.3 \
+ rpc_svc_err.3 svcerr_decode.3 \
+ rpc_svc_err.3 svcerr_noproc.3 \
+ rpc_svc_err.3 svcerr_noprog.3 \
+ rpc_svc_err.3 svcerr_progvers.3 \
+ rpc_svc_err.3 svcerr_systemerr.3 \
+ rpc_svc_err.3 svcerr_weakauth.3 \
+ rpc_svc_reg.3 rpc_reg.3 \
+ rpc_svc_reg.3 svc_reg.3 \
+ rpc_svc_reg.3 svc_unreg.3 \
+ rpc_svc_reg.3 svc_auth_reg.3 \
+ rpc_svc_reg.3 xprt_register.3 \
+ rpc_svc_reg.3 xprt_unregister.3 \
+ rpcbind.3 rpcb_getmaps.3 \
+ rpcbind.3 rpcb_getaddr.3 \
+ rpcbind.3 rpcb_gettime.3 \
+ rpcbind.3 rpcb_rmtcall.3 \
+ rpcbind.3 rpcb_set.3 \
+ rpcbind.3 rpcb_unset.3 \
+ rpc_soc.3 authunix_create.3 \
+ rpc_soc.3 authunix_create_default.3 \
+ rpc_soc.3 callrpc.3 \
+ rpc_soc.3 clnt_broadcast.3 \
+ rpc_soc.3 clntraw_create.3 \
+ rpc_soc.3 clnttcp_create.3 \
+ rpc_soc.3 clntudp_bufcreate.3 \
+ rpc_soc.3 clntudp_create.3 \
+ rpc_soc.3 get_myaddress.3 \
+ rpc_soc.3 pmap_getmaps.3 \
+ rpc_soc.3 pmap_getport.3 \
+ rpc_soc.3 pmap_rmtcall.3 \
+ rpc_soc.3 pmap_set.3 \
+ rpc_soc.3 pmap_unset.3 \
+ rpc_soc.3 registerrpc.3 \
+ rpc_soc.3 rpc_createerr.3 \
+ rpc_soc.3 svc_fds.3 \
+ rpc_soc.3 svc_fdset.3 \
+ rpc_soc.3 svc_getcaller.3 \
+ rpc_soc.3 svc_register.3 \
+ rpc_soc.3 svc_unregister.3 \
+ rpc_soc.3 svcfd_create.3 \
+ rpc_soc.3 svcraw_create.3 \
+ rpc_soc.3 svctcp_create.3 \
+ rpc_soc.3 svcudp_bufcreate.3 \
+ rpc_soc.3 xdr_pmap.3 \
+ rpc_soc.3 xdr_pmaplist.3
diff --git a/lib/libc/rpc/README b/lib/libc/rpc/README
index ad9d70f99056..c915fad283c6 100644
--- a/lib/libc/rpc/README
+++ b/lib/libc/rpc/README
@@ -1,233 +1,176 @@
-RPCSRC 4.0 7/11/89
+$FreeBSD$
+
+PLEASE READ THE DISCLAIMER FILE. DO NOT CALL THE SUN MICROSYSTEMS SUPPORT
+LINE WITH QUESTIONS ON THIS RELEASE. THEY CANNOT ANSWER QUESTIONS ABOUT THIS
+UNSUPPORTED SOURCE RELEASE.
+
+TIRPCSRC 2.3 29 Aug 1994
+
+This distribution contains SunSoft's implementation of transport-independent
+RPC (TI-RPC), External Data Representation (XDR), and various utilities and
+documentation. These libraries and programs form the base of Open Network
+Computing (ONC), and are derived directly from the Solaris 2.3 source.
+
+Previous releases of RPC Source based on SunOS 4.x were ported to 4.2BSD and
+used Sockets as the transport interface. These versions were
+transport-specific RPC (TS-RPC).
+
+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 is a native source release, that is, it is compatible for
+building on Solaris 2.3. This release was built on Solaris 2.3 using SunPro
+SPARCompiler 2.0.1.
+
+Solaris 2.3 is based on System V, Release 4 (SVR4), and while this release
+should be mostly compatible with other SVR4 systems, some Solaris facilities
+that are assumed may not be available. In particular, this release uses the
+Makefile format supported by SparcCompiler 2.0.1. Second, the Secure RPC
+routines use the Solaris Name Service Switch to access public-key credential
+databases. This code will need to be ported if your system does not support
+the Name Service Switch. Finally, this release uses the synchronization
+interfaces of UI Threads to make certain interfaces thread-safe. These
+interfaces are found in libthread in Solaris 2.3 and later.
+
+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. Note that the Solaris 2.3 Encryption Kit is only available
+within the United States. (PLEASE NOTE: The RPC implementation found in
+Solaris 2.3's libnsl does *not* have this requirement; linking with libcrypt
+is only a requirement for the TIRPCSRC 2.3 version of librpc.)
+
+
+DOCUMENTATION NOTE
+
+The documentation found in the doc directory are derived from the Solaris 2.3
+Network Interfaces Programming Guide. A small number of compile examples are
+given, and these use libnsl to link in the RPC library. This release builds
+the RPC library as librpc. To use this release's librpc, use the link command
+"-lrpc -lnsl -lcrypt". This links the application with TIRPCSRC 2.3's librpc
+for RPC routines, Solaris's libnsl for other networking functions, and
+libcrypt for the cbc_crypt() and ecb_crypt functions.
+
+
+WHY IS THIS RELEASE BEING DONE?
+
+This release is being distributed to make the Sun implementation of the ONC
+technologies available for reference and porting to non-Solaris platforms.
+The current release is a native source distribution, and provides services
+that are already available on Solaris 2.3 (such as the RPC headers, the RPC
+library in libnsl, rpcbind, rpcinfo, etc.). It is not our intention to
+replace these services. See the DISCLAIMER for further information about the
+legal status of this release.
+
+
+WHAT'S NEW IN THIS RELEASE: TIRPCSRC 2.3
+
+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.
+
+4. The Remote Asynchronous Calls (RAC) library is now included. RAC was
+ first introduced in TIRPCSRC 1.0, and was bundled with librpc. It is
+ now a separate library. The asynchronous call model that RAC provides
+ can be achieved by using threads for making client-side RPC calls.
+ The ONC Technology group recommends using threads (where possible) to
+ achieve asynchrony rather than RAC. See the rpc_rac(3n) manual page
+ for details.
-This distribution contains Sun Microsystem's implementation of the
-RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also
-included is complete documentation, utilities, RPC service
-specification files, and demonstration services in the format used by
-the RPC protocol compiler (rpcgen). See WHAT'S NEW below for
-details.
-NOTE ABOUT SECURE RPC:
+ROADMAP
-This release of RPCSRC contains most of the code needed to implement
-Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
-doc/rpc.rfc.ms). Due to legal considerations, we are unable to
-distribute an implementation of DES, the Data Encryption Standard, which
-Secure RPC requires. For this reason, all of the files, documentation, and
-programs associated with Secure RPC have been placed into a separate
-directory, secure_rpc. The RPC library contained in the main body of this
-release *DOES NOT* support Secure RPC. See secure_rpc/README for more
-details. (A DES library was posted in Volume 18 of comp.sources.unix.)
+The directory hierarchy is as follows:
-If you wish to report bugs found in this release, send mail to:
+ cmd/ Utilities
+ cmd/rpcgen The RPC Language compiler (for .x files)
+ cmd/rpcbind The RPC bindery and portmapper
+ cmd/rpcinfo RPC bindery query utility
+ cmd/keyserv The Secure RPC keyserver
+ cmd/demo Some simple ONC demo services
-Portable ONC/NFS
-Sun Microsystems, Inc
-MS 12-33
-2550 Garcia Avenue
-Mountain View, CA 94043
+ doc/ Postscript versions of ONC documentation
-or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
+ head/ Header files
+ head/rpcsvc RPCL (.x) specifications for various ONC services, and
+ header files.
-ROADMAP
+ lib/ Libraries
+ lib/librpc The RPC and XDR library
+ lib/librac The Remote Asynchronous Calls (RAC) library
-The directory hierarchy is as follows:
+ man/ Manual pages for the RPC library and utilities.
- demo/ Various demonstration services
- demo/dir Remote directory lister
- demo/msg Remote console message delivery service
- demo/sort Remote sort service
+ uts/common/rpc RPC header files
- doc/ Documentation for RPC, XDR and NFS in "-ms" format.
- etc/ Utilities (rpcinfo and portmap). portmap must be
- started by root before any other RPC network services are
- used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
- man/ Manual pages for RPC library, rpcgen, and utilities.
+BUILD INSTRUCTIONS
- rpc/ The RPC and XDR library. SEE BELOW
- FOR BUGFIX TO 4.2BSD COMPILER.
+Prior to building the release, you must define the SRC environment variable
+to be the path to the top-level Makefile. For example, if /usr/src/tirpcsrc
+is where to top-level Makefile is located, execute this command prior to
+building the release:
- rpcgen/ The RPC Language compiler (for .x files)
+ setenv SRC /usr/src/tirpcsrc (csh)
+or
+ SRC=/usr/src/tirpcsrc; export SRC (sh)
- rpcsvc/ Service definition files for various services and the
- server and client code for the Remote Status service.
+The sources in the lib directory depend on header files installed from head
+and uts/common/rpc, and the programs in the cmd directory depend on libraries
+from lib. Therefore, you should do a "make install" to build the release.
- secure_rpc/ The files in this directory are used to build a version of
- the RPC library with DES Authentication. See the README
- file in that directory for more details.
+The top-level Makefile builds the release. The "ROOT" macro defines where the
+headers and libraries are installed. The default for ROOT is "/proto". You
+may change this by either modifiying Makefile.master, or issuing the build
+command with a new definition for ROOT:
-BUILD INSTRUCTIONS
+ make install ROOT=/opt/onc
+
+You will of course need write privileges for the destination directory.
+The headers, libraries and executables will be built and installed under the
+ROOT.
-Makefiles can be found in all directories except for man. The
-Makefile in the top directory will cause these others to be invoked
-(except for in the doc, man and demo directories), in turn building the
-entire release.
-
-WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
-IN /usr/include, /usr/lib, /usr/bin and /etc.
-
-The master RPC include file, rpc/rpc.h, is used by all programs and
-routines that use RPC. It includes other RPC and system include files
-needed by the RPC system. PLEASE NOTE: If your system has NFS, it
-may have been based on Sun's NFS Source. The include files installed
-by this package may duplicate include files you will find on your NFS
-system. The RPCSRC 4.0 include files are upwardly compatible to all
-NFS Source include files as of the date of this distribution (not
-including any new definitions or declarations added by your system
-vendor). HOWEVER: Please read the comments towards the end of
-rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the
-inclusion of that file if the structures it defines are already
-defined by your system's include files.
-
-After making any compiler fixes that are needed (see below), at
-the top directory, type:
-
- make install
-
-For all installations, the Makefile macro DESTDIR is prepended to the
-installation path. It is defined to be null in the Makefiles, so
-installations are relative to root. (You will probably need root
-privileges for installing the files under the default path.) To
-install the files under some other tree (e.g., /usr/local), use the
-command:
-
- make install DESTDIR=/usr/local
-
-This will place the include files in /usr/local/usr/include, the RPC
-library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
-utilities in /usr/local/etc. You'll have to edit the Makefiles or
-install the files by hand if you want to do anything other than this
-kind of relocation of the installation tree.
-
-The RPC library will be built and installed first. By default it is
-installed in /usr/lib as "librpclib.a". The directory
-/usr/include/rpc will also be created, and several header files will
-be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES.
-
-The programs in etc/ link in routines from librpclib.a. If you change
-where it is installed, be sure to edit etc/'s Makefile to reflect this.
-These programs are installed in /etc. PORTMAP MUST BE RUNNING ON
-YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
-
-rpcgen is installed in /usr/bin. This program is required to build
-the demonstration services in demo and the rstat client and server in
-rpcsvc/.
-
-The rpcsvc/ directory will install its files in the directory
-/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be
-compiled and installed in /etc. If you wish to make this service
-available, you should either start this service when needed or have
-it started at boot time by invoking it in your /etc/rc.local script.
-(Be sure that portmap is started first!) Sun has modified its
-version of inetd to automatically start RPC services. (Use "make
-LIB=" when building rstat on a Sun Workstation.) The Remote Status
-client (rstat) will be installed in /usr/bin. This program queries
-the rstat_svc on a remote host and prints a system status summary
-similar to the one printed by "uptime".
-
-The documentation is not built during the "make install" command.
-Typing "make" in the doc directory will cause all of the manuals to
-be formatted using nroff into a single file. We have had a report
-that certain "troff" equivalents have trouble processing the full
-manual. If you have trouble, try building the manuals individually
-(see the Makefile).
The demonstration services in the demo directory are not built by the
-top-level "make install" command. To build these, cd to the demo
-directory and enter "make". The three services will be built.
+top-level "make install" command. To build these, cd to the cmd/demo
+directory and enter "make". The four services will be built.
RPCGEN MUST BE INSTALLED in a path that make can find. To run the
-services, start the portmap program as root and invoke the service
+services, rpcbind must be running, then invoke the service
(you probably will want to put it in the background). rpcinfo can be
used to check that the service succeeded in getting registered with
-portmap, and to ping the service (see rpcinfo's man page). You can
+rpcbind, and to ping the service (see rpcinfo's man page). You can
then use the corresponding client program to exercise the service.
-To build these services on a Sun workstation, you must prevent the
-Makefile from trying to link the RPC library (as these routines are
-already a part of Sun's libc). Use: "make LIB=".
-
-BUGFIX FOR 4.3BSD COMPILER
-
-The use of a 'void *' declaration for one of the arguments in
-the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
-in the 4.3BSD compiler. The bug is fixed by the following change to
-the compiler file mip/manifest.h:
-
-*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987
---- manifest.h.r1.2 Mon Nov 23 18:58:17 1987
-***************
-*** 21,27 ****
- /*
- * Bogus type values
- */
-! #define TNULL PTR /* pointer to UNDEF */
- #define TVOID FTN /* function returning UNDEF (for void) */
-
- /*
---- 21,27 ----
- /*
- * Bogus type values
- */
-! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
- #define TVOID FTN /* function returning UNDEF (for void) */
-
- /*
-
-If you cannot fix your compiler, change the declaration in reply_proc()
-from 'void *' to 'char *'.
-
-BUGFIX FOR 4.2BSD COMPILER
-
-Unpatched 4.2BSD compilers complain about valid C. You can make old
-compilers happy by changing some voids to ints. However, the fix to
-the 4.2 VAX compiler is as follows (to mip/trees.c):
-
-*** trees.c.r1.1 Mon May 11 13:47:58 1987
---- trees.c.r1.2 Wed Jul 2 18:28:52 1986
-***************
-*** 1247,1253 ****
- if(o==CAST && mt1==0)return(TYPL+TYMATCH);
- if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
- else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
-! else if( mt12 == 0 ) break;
- else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
- else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
- break;
---- 1261,1269 ----
- if(o==CAST && mt1==0)return(TYPL+TYMATCH);
- if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
- else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
-! /* if right is TVOID and looks like a CALL, is not ok */
-! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
-! break;
- else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
- else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
- break;
-
-WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
-
-The previous release was RPCSRC 3.9. As with all previous releases,
-this release is based directly on files from Sun Microsystem's
-implementation.
-
-Upgrade from RPCSRC 3.9
-
-1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have
- been integrated into this release.
-
-Secure RPC (in the secure_rpc/ directory)
-
-2) DES Authentication routines and programs are provided.
-3) A new manual, "Secure NFS" is provided, which describes Secure RPC
- and Secure NFS.
-4) Skeleton routines and manual pages are provided which describe the
- DES encryption procedures required by Secure RPC. HOWEVER, NO DES
- ROUTINE IS PROVIDED.
-
-New Functionality
-
-5) rpcinfo can now be used to de-register services from the portmapper
- which may have terminated abnormally.
-6) A new client, rstat, is provided which queries the rstat_svc and
- prints a status line similar to the one displayed by "uptime".
+
+
+BUILDING ONC APPLICATIONS
+
+See the Makefiles in the demonstration services for examples of building
+ONC applications with this release. The $(ROOT)/usr/include directory
+must be included in the compiler header file search path (-I), and the
+$(ROOT)/usr/lib directory must be included in the linker library file search
+path (-L). Also, to run executables built dynamically, the shared library
+search path (LD_LIBRARY_PATH) must also include $(ROOT)/usr/lib. In addition
+to linking in this release's librpc (via -lrpc), you must also link with
+Solaris's libnsl (-lnsl) and the US domestic version of libcrypt (-lcrypt).
+
diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c
index 51cfb1f62bb3..e154cd2fe315 100644
--- a/lib/libc/rpc/auth_des.c
+++ b/lib/libc/rpc/auth_des.c
@@ -1,3 +1,4 @@
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -32,59 +33,58 @@
/*
* auth_des.c, client-side implementation of DES authentication
*/
+#include "reentrant.h"
+#include "namespace.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/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_des.h>
+#include <rpc/clnt.h>
+#include <rpc/xdr.h>
#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */
#include <sys/socket.h>
#undef NIS
#include <rpcsvc/nis.h>
+#include "un-namespace.h"
#if defined(LIBC_SCCS) && !defined(lint)
/* from: static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */
static const char rcsid[] = "$FreeBSD$";
#endif
-extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *,
- char *, char **, struct sockaddr_in * ));
-extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *));
-extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * ));
-extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * ));
-
-#define MILLION 1000000L
-#define RTIME_TIMEOUT 5 /* seconds to wait for sync */
+#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)
-#define debug(msg) /*printf("%s\n", msg) */
+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();
-static bool_t authdes_marshal();
-static bool_t authdes_validate();
-static bool_t authdes_refresh();
-static void authdes_destroy();
-static struct auth_ops authdes_ops = {
- authdes_nextverf,
- authdes_marshal,
- authdes_validate,
- authdes_refresh,
- authdes_destroy
-};
-#ifdef foo
-static bool_t synchronize __P(( struct sockaddr *, struct timeval *));
-#endif
+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 *"
*/
@@ -95,10 +95,10 @@ struct ad_private {
u_int ad_servernamelen; /* length of name, rounded up */
u_int ad_window; /* client specified window */
bool_t ad_dosync; /* synchronize? */
- struct sockaddr ad_syncaddr; /* remote host to synch with */
+ 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_long ad_nickname; /* server's nickname for client */
+ 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 */
@@ -108,106 +108,50 @@ struct ad_private {
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 *);
+
/*
- * Create the client des authentication object
- */
+ * 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_create(servername, window, syncaddr, ckey)
- char *servername; /* network name of server */
- u_int window; /* time to live */
- struct sockaddr *syncaddr; /* optional addr of host to sync with */
- des_block *ckey; /* optional conversation key to use*/
+authdes_seccreate(const char *servername, const u_int win,
+ const char *timehost, const des_block *ckey)
{
-
- AUTH *auth;
- struct ad_private *ad;
- char namebuf[MAXNETNAMELEN+1];
- u_char pkey_data[1024];
-
- if (!getpublickey(servername, pkey_data))
- return(NULL);
-
- /*
- * Allocate everything now
- */
- auth = ALLOC(AUTH);
- ad = ALLOC(struct ad_private);
- (void) getnetname(namebuf);
-
- ad->ad_fullnamelen = RNDUP(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 (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
- ad->ad_servername == NULL) {
- debug("authdes_create: out of memory");
- goto failed;
- }
-
- /*
- * Set up private data
- */
- bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
- bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
- bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1);
- if (syncaddr != NULL) {
- ad->ad_syncaddr = *syncaddr;
- ad->ad_dosync = TRUE;
- } else {
- ad->ad_dosync = FALSE;
- }
- ad->ad_window = window;
- if (ckey == NULL) {
- if (key_gendes(&auth->ah_key) < 0) {
- debug("authdes_create: unable to gen conversation key");
- return (NULL);
- }
- } else {
- auth->ah_key = *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);
}
- /*
- * 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)) {
- goto failed;
- }
- return (auth);
-
-failed:
- if (auth != NULL)
- FREE(auth, sizeof(AUTH));
- if (ad != NULL)
- FREE(ad, sizeof(struct ad_private));
- if (ad->ad_fullname != NULL)
- FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
- if (ad->ad_servername != NULL)
- FREE(ad->ad_servername, ad->ad_servernamelen + 1);
- 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 authdes_create which takes the public key
+ * 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_create(servername, pkey, window, timehost, ckey, srvr)
- char *servername; /* network name of server */
- netobj *pkey; /* public key of server */
- u_int window; /* time to live */
- char *timehost; /* optional hostname to sync with */
- des_block *ckey; /* optional conversation key to use */
- nis_server *srvr; /* optional NIS+ server struct */
+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;
@@ -218,12 +162,12 @@ authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
*/
auth = ALLOC(AUTH);
if (auth == NULL) {
- debug("authdes_pk_create: out of memory");
+ syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
return (NULL);
}
ad = ALLOC(struct ad_private);
if (ad == NULL) {
- debug("authdes_pk_create: out of memory");
+ syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
goto failed;
}
ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
@@ -242,13 +186,13 @@ authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
- debug("authdes_pk_create: out of memory");
+ 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) {
- debug("authdes_pk_create: out of memory");
+ syslog(LOG_ERR, "authdes_seccreate: out of memory");
goto failed;
}
memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
@@ -264,7 +208,8 @@ authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
ad->ad_window = window;
if (ckey == NULL) {
if (key_gendes(&auth->ah_key) < 0) {
- debug("authdes_pk_create: unable to gen conversation key");
+ syslog(LOG_ERR,
+ "authdes_seccreate: keyserv(1m) is unable to generate session key");
goto failed;
}
} else {
@@ -276,10 +221,10 @@ authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
*/
auth->ah_cred.oa_flavor = AUTH_DES;
auth->ah_verf.oa_flavor = AUTH_DES;
- auth->ah_ops = &authdes_ops;
+ auth->ah_ops = authdes_ops();
auth->ah_private = (caddr_t)ad;
- if (!authdes_refresh(auth)) {
+ if (!authdes_refresh(auth, NULL)) {
goto failed;
}
ad->ad_nis_srvr = NULL; /* not needed any longer */
@@ -296,13 +241,14 @@ failed:
if (ad->ad_timehost)
FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
if (ad->ad_netid)
- free(ad->ad_netid);
+ FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
if (ad->ad_uaddr)
- free(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
*/
@@ -313,30 +259,27 @@ failed:
*/
/*ARGSUSED*/
static void
-authdes_nextverf(auth)
- AUTH *auth;
+authdes_nextverf(AUTH *auth)
{
/* what the heck am I supposed to do??? */
}
-
/*
* 2. Marshal
*/
static bool_t
-authdes_marshal(auth, xdrs)
- AUTH *auth;
- XDR *xdrs;
+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;
- long len;
- int32_t *ixdr;
+ int len;
+ register rpc_inline_t *ixdr;
/*
* Figure out the "time", accounting for any time difference
@@ -345,30 +288,32 @@ authdes_marshal(auth, xdrs)
(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;
- if (ad->ad_timestamp.tv_usec >= MILLION) {
- ad->ad_timestamp.tv_usec -= MILLION;
- ad->ad_timestamp.tv_sec += 1;
+ 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 = (int32_t *)cryptbuf;
- IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
- IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
+ 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_LONG(ixdr, ad->ad_window);
- IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
+ 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,
- 2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
+ (u_int) 2 * sizeof (des_block),
+ DES_ENCRYPT | DES_HW, (char *)&ivec);
} else {
status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
- sizeof(des_block), DES_ENCRYPT | DES_HW);
+ (u_int) sizeof (des_block),
+ DES_ENCRYPT | DES_HW);
}
if (DES_FAILED(status)) {
- debug("authdes_marshal: DES encryption failure");
+ syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
return (FALSE);
}
ad->ad_verf.adv_xtimestamp = cryptbuf[0];
@@ -391,21 +336,21 @@ authdes_marshal(auth, xdrs)
}
if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
- IXDR_PUT_LONG(ixdr, AUTH_DES);
- IXDR_PUT_LONG(ixdr, len);
+ IXDR_PUT_INT32(ixdr, AUTH_DES);
+ IXDR_PUT_INT32(ixdr, len);
} else {
- ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor));
- ATTEMPT(xdr_putlong(xdrs, &len));
+ 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_LONG(ixdr, AUTH_DES);
- IXDR_PUT_LONG(ixdr, len);
+ IXDR_PUT_INT32(ixdr, AUTH_DES);
+ IXDR_PUT_INT32(ixdr, len);
} else {
- ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor));
- ATTEMPT(xdr_putlong(xdrs, &len));
+ ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
+ ATTEMPT(xdr_putint32(xdrs, &len));
}
ATTEMPT(xdr_authdes_verf(xdrs, verf));
return (TRUE);
@@ -416,89 +361,92 @@ authdes_marshal(auth, xdrs)
* 3. Validate
*/
static bool_t
-authdes_validate(auth, rverf)
- AUTH *auth;
- struct opaque_auth *rverf;
+authdes_validate(AUTH *auth, struct opaque_auth *rverf)
{
+/* LINTED pointer alignment */
struct ad_private *ad = AUTH_PRIVATE(auth);
struct authdes_verf verf;
int status;
- register u_long *ixdr;
+ register uint32_t *ixdr;
+ des_block buf;
if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
return (FALSE);
}
- ixdr = (u_long *)rverf->oa_base;
- verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
- verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
- verf.adv_int_u = (u_long)*ixdr++; /* nickname not XDR'd ! */
+/* 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 *)&verf.adv_xtimestamp,
- sizeof(des_block), DES_DECRYPT | DES_HW);
+ status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
+ (u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
if (DES_FAILED(status)) {
- debug("authdes_validate: DES decryption failure");
+ syslog(LOG_ERR, "authdes_validate: DES decryption failure");
return (FALSE);
}
/*
- * xdr the decrypted timestamp
+ * xdr the decrypted timestamp
*/
- ixdr = (u_long *)verf.adv_xtimestamp.c;
- verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
- verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+/* 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) {
- debug("authdes_validate: verifier mismatch\n");
+ 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);
+ 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 *auth;
+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 &&
-#ifdef old
- !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
-#else
- !__rpc_get_time_offset(&ad->ad_timediff,ad->ad_nis_srvr,
- ad->ad_timehost, &(ad->ad_uaddr),
- (struct sockaddr_in *)&(ad->ad_syncaddr))) {
-#endif
- /*
- * Hope the clocks are synced!
- */
- ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
- ad->ad_dosync = 0;
- debug("authdes_refresh: unable to synchronize with server");
+ if (ad->ad_dosync) {
+ ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
+ ad->ad_timehost, &(ad->ad_uaddr),
+ &(ad->ad_netid));
+ 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 = strlen((char *)ad->ad_pkey) + 1;
+ pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
- debug("authdes_create: unable to encrypt conversation key");
+ syslog(LOG_INFO,
+ "authdes_refresh: keyserv(1m) is unable to encrypt session key");
return (FALSE);
}
cred->adc_fullname.key = ad->ad_xkey;
@@ -512,43 +460,39 @@ authdes_refresh(auth)
* 5. Destroy
*/
static void
-authdes_destroy(auth)
- AUTH *auth;
+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);
- FREE(ad, sizeof(struct ad_private));
+ 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));
}
-
-#ifdef old
-/*
- * Synchronize with the server at the given address, that is,
- * adjust timep to reflect the delta between our clocks
- */
-static bool_t
-synchronize(syncaddr, timep)
- struct sockaddr *syncaddr;
- struct timeval *timep;
+static struct auth_ops *
+authdes_ops(void)
{
- struct timeval mytime;
- struct timeval timeout;
-
- timeout.tv_sec = RTIME_TIMEOUT;
- timeout.tv_usec = 0;
- if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) {
- return (FALSE);
- }
- (void) gettimeofday(&mytime, (struct timezone *)NULL);
- timep->tv_sec -= mytime.tv_sec;
- if (mytime.tv_usec > timep->tv_usec) {
- timep->tv_sec -= 1;
- timep->tv_usec += MILLION;
- }
- timep->tv_usec -= mytime.tv_usec;
- return (TRUE);
+ 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);
}
-#endif
diff --git a/lib/libc/rpc/auth_none.c b/lib/libc/rpc/auth_none.c
index 9649df3ab51b..403e00d571f4 100644
--- a/lib/libc/rpc/auth_none.c
+++ b/lib/libc/rpc/auth_none.c
@@ -1,3 +1,5 @@
+/* $NetBSD: auth_none.c,v 1.13 2000/01/22 22:19:17 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,10 +29,11 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
+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
/*
@@ -41,96 +44,135 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "reentrant.h"
+#include "namespace.h"
+#include <assert.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
-#define MAX_MARSHEL_SIZE 20
+#include "un-namespace.h"
+
+#define MAX_MARSHAL_SIZE 20
/*
* Authenticator operations routines
*/
-static void authnone_verf();
-static void authnone_destroy();
-static bool_t authnone_marshal();
-static bool_t authnone_validate();
-static bool_t authnone_refresh();
-
-static struct auth_ops ops = {
- authnone_verf,
- authnone_marshal,
- authnone_validate,
- authnone_refresh,
- authnone_destroy
-};
+
+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_MARSHEL_SIZE];
+ char marshalled_client[MAX_MARSHAL_SIZE];
u_int mcnt;
} *authnone_private;
AUTH *
authnone_create()
{
- register struct authnone_private *ap = authnone_private;
+ struct authnone_private *ap = authnone_private;
XDR xdr_stream;
- register XDR *xdrs;
+ 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)
+ 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 = &ops;
+ ap->no_client.ah_ops = authnone_ops();
xdrs = &xdr_stream;
- xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_SIZE,
- XDR_ENCODE);
+ 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(client, xdrs)
- AUTH *client;
- XDR *xdrs;
+authnone_marshal(AUTH *client, XDR *xdrs)
{
- register struct authnone_private *ap = authnone_private;
+ struct authnone_private *ap;
+ bool_t dummy;
+ extern mutex_t authnone_lock;
- if (ap == 0)
- return (0);
- return ((*xdrs->x_ops->x_putbytes)(xdrs,
- ap->marshalled_client, ap->mcnt));
+ 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()
+authnone_verf(AUTH *client)
{
}
+/*ARGSUSED*/
static bool_t
-authnone_validate()
+authnone_validate(AUTH *client, struct opaque_auth *opaque)
{
return (TRUE);
}
+/*ARGSUSED*/
static bool_t
-authnone_refresh()
+authnone_refresh(AUTH *client, void *dummy)
{
return (FALSE);
}
+/*ARGSUSED*/
static void
-authnone_destroy()
+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);
+}
diff --git a/lib/libc/rpc/auth_time.c b/lib/libc/rpc/auth_time.c
index 114d59d4428c..f352c6d5eda9 100644
--- a/lib/libc/rpc/auth_time.c
+++ b/lib/libc/rpc/auth_time.c
@@ -45,20 +45,11 @@
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/rpc_com.h>
+#include <rpc/rpcb_prot.h>
#undef NIS
#include <rpcsvc/nis.h>
#include "un-namespace.h"
-/*
- * FreeBSD currently uses RPC 4.0, which uses portmap rather than
- * rpcbind. Consequently, we need to fake up these values here.
- * Luckily, the RPCB_GETTIME procedure uses only base XDR data types
- * so we don't need anything besides these magic numbers.
- */
-#define RPCBPROG (u_long)100000
-#define RPCBVERS (u_long)3
-#define RPCBPROC_GETTIME (u_long)6
-
#ifdef TESTING
#define msg(x) printf("ERROR: %s\n", x)
/* #define msg(x) syslog(LOG_ERR, "%s", x) */
diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c
index dced8f2104b3..37d0ce9f0983 100644
--- a/lib/libc/rpc/auth_unix.c
+++ b/lib/libc/rpc/auth_unix.c
@@ -1,3 +1,5 @@
+/* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,10 +29,11 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
+static char *sccsid = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";
#endif
/*
@@ -45,33 +48,31 @@ static char *rcsid = "$FreeBSD$";
*
*/
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#include <sys/param.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
+#include "un-namespace.h"
-/*
- * Unix authenticator operations vector
- */
-static void authunix_nextverf();
-static bool_t authunix_marshal();
-static bool_t authunix_validate();
-static bool_t authunix_refresh();
-static void authunix_destroy();
-
-static struct auth_ops auth_unix_ops = {
- authunix_nextverf,
- authunix_marshal,
- authunix_validate,
- authunix_refresh,
- authunix_destroy
-};
+/* 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.
@@ -85,21 +86,6 @@ struct audata {
};
#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
-static void marshal_new_auth();
-
-/*
- * This goop is here because some servers refuse to accept a
- * credential with more than some number (usually 8) supplementary
- * groups. Blargh!
- */
-static int authunix_maxgrouplist = 0;
-
-void
-set_rpc_maxgrouplist(int num)
-{
- authunix_maxgrouplist = num;
-}
-
/*
* Create a unix style authenticator.
* Returns an auth handle with the given stuff in it.
@@ -109,60 +95,56 @@ authunix_create(machname, uid, gid, len, aup_gids)
char *machname;
int uid;
int gid;
- register int len;
+ int len;
int *aup_gids;
{
struct authunix_parms aup;
char mymem[MAX_AUTH_BYTES];
struct timeval now;
XDR xdrs;
- register AUTH *auth;
- register struct audata *au;
+ AUTH *auth;
+ struct audata *au;
/*
* Allocate and set up auth handle
*/
- auth = (AUTH *)mem_alloc(sizeof(*auth));
+ au = NULL;
+ auth = mem_alloc(sizeof(*auth));
#ifndef _KERNEL
if (auth == NULL) {
- (void)fprintf(stderr, "authunix_create: out of memory\n");
- return (NULL);
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
}
#endif
- au = (struct audata *)mem_alloc(sizeof(*au));
+ au = mem_alloc(sizeof(*au));
#ifndef _KERNEL
if (au == NULL) {
- (void)fprintf(stderr, "authunix_create: out of memory\n");
- return (NULL);
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
}
#endif
- auth->ah_ops = &auth_unix_ops;
+ 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, (struct timezone *)0);
+ (void)gettimeofday(&now, NULL);
aup.aup_time = now.tv_sec;
aup.aup_machname = machname;
aup.aup_uid = uid;
aup.aup_gid = gid;
- /* GW: continuation of max group list hack */
- if(authunix_maxgrouplist != 0) {
- aup.aup_len = ((len < authunix_maxgrouplist) ? len
- : authunix_maxgrouplist);
- } else {
- aup.aup_len = (u_int)len;
- }
+ 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))
+ if (! xdr_authunix_parms(&xdrs, &aup))
abort();
au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
au->au_origcred.oa_flavor = AUTH_UNIX;
@@ -170,11 +152,11 @@ authunix_create(machname, uid, gid, len, aup_gids)
au->au_origcred.oa_base = mem_alloc((u_int) len);
#else
if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
- (void)fprintf(stderr, "authunix_create: out of memory\n");
- return (NULL);
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
}
#endif
- memcpy(au->au_origcred.oa_base, mymem, (u_int)len);
+ memmove(au->au_origcred.oa_base, mymem, (size_t)len);
/*
* set auth handle to reflect new cred.
@@ -182,6 +164,17 @@ authunix_create(machname, uid, gid, len, aup_gids)
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
}
/*
@@ -191,32 +184,29 @@ authunix_create(machname, uid, gid, len, aup_gids)
AUTH *
authunix_create_default()
{
- register int len;
- char machname[MAX_MACHINE_NAME + 1];
- register int uid;
- register int gid;
- int gids[NGRPS];
- int i;
- gid_t real_gids[NGROUPS];
-
- if (gethostname(machname, MAX_MACHINE_NAME) == -1)
+ int len;
+ char machname[MAXHOSTNAMELEN + 1];
+ uid_t uid;
+ gid_t gid;
+ gid_t gids[NGRPS];
+
+ if (gethostname(machname, sizeof machname) == -1)
abort();
- machname[MAX_MACHINE_NAME] = 0;
- uid = (int)geteuid();
- gid = (int)getegid();
- if ((len = getgroups(NGROUPS, real_gids)) < 0)
+ machname[sizeof(machname) - 1] = 0;
+ uid = geteuid();
+ gid = getegid();
+ if ((len = getgroups(NGRPS, gids)) < 0)
abort();
- if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */
- for(i = 0; i < len; i++) {
- gids[i] = (int)real_gids[i];
- }
- return (authunix_create(machname, uid, gid, len, gids));
+ /* XXX: interface problem; those should all have been unsigned */
+ return (authunix_create(machname, (int)uid, (int)gid, len,
+ (int *)gids));
}
/*
* authunix operations
*/
+/* ARGSUSED */
static void
authunix_nextverf(auth)
AUTH *auth;
@@ -229,22 +219,30 @@ authunix_marshal(auth, xdrs)
AUTH *auth;
XDR *xdrs;
{
- register struct audata *au = AUTH_PRIVATE(auth);
+ 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)
- register AUTH *auth;
- struct opaque_auth verf;
+ AUTH *auth;
+ struct opaque_auth *verf;
{
- register struct audata *au;
+ struct audata *au;
XDR xdrs;
- if (verf.oa_flavor == AUTH_SHORT) {
+ 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);
+ 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,
@@ -265,14 +263,15 @@ authunix_validate(auth, verf)
}
static bool_t
-authunix_refresh(auth)
- register AUTH *auth;
+authunix_refresh(AUTH *auth, void *dummy)
{
- register struct audata *au = AUTH_PRIVATE(auth);
+ struct audata *au = AUTH_PRIVATE(auth);
struct authunix_parms aup;
struct timeval now;
XDR xdrs;
- register int stat;
+ int stat;
+
+ assert(auth != NULL);
if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
/* there is no hope. Punt */
@@ -282,7 +281,7 @@ authunix_refresh(auth)
/* first deserialize the creds back into a struct authunix_parms */
aup.aup_machname = NULL;
- aup.aup_gids = (int *)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);
@@ -290,7 +289,7 @@ authunix_refresh(auth)
goto done;
/* update the time and serialize in place */
- (void)gettimeofday(&now, (struct timezone *)0);
+ (void)gettimeofday(&now, NULL);
aup.aup_time = now.tv_sec;
xdrs.x_op = XDR_ENCODE;
XDR_SETPOS(&xdrs, 0);
@@ -309,10 +308,13 @@ done:
static void
authunix_destroy(auth)
- register AUTH *auth;
+ AUTH *auth;
{
- register struct audata *au = AUTH_PRIVATE(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)
@@ -323,7 +325,7 @@ authunix_destroy(auth)
if (auth->ah_verf.oa_base != NULL)
mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
- mem_free((caddr_t)auth, sizeof(*auth));
+ mem_free(auth, sizeof(*auth));
}
/*
@@ -332,18 +334,40 @@ authunix_destroy(auth)
*/
static void
marshal_new_auth(auth)
- register AUTH *auth;
+ AUTH *auth;
{
- XDR xdr_stream;
- register XDR *xdrs = &xdr_stream;
- register struct audata *au = AUTH_PRIVATE(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)))) {
- perror("auth_none.c - Fatal marshalling problem");
- } else {
+ (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
+ 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);
+}
diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c
index 14679c00a9cc..f60e79f9fa6b 100644
--- a/lib/libc/rpc/authdes_prot.c
+++ b/lib/libc/rpc/authdes_prot.c
@@ -1,6 +1,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI";
#endif
+/* $FreeBSD$ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -30,17 +31,19 @@ static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88
* Mountain View, California 94043
*/
/*
- * Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
/*
* authdes_prot.c, XDR routines for DES authentication
*/
+#include "namespace.h"
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_des.h>
+#include "un-namespace.h"
#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
@@ -55,12 +58,16 @@ xdr_authdes_cred(xdrs, cred)
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)));
+ 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)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname,
+ sizeof(cred->adc_nickname)));
return (TRUE);
default:
return (FALSE);
@@ -76,7 +83,9 @@ xdr_authdes_verf(xdrs, 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)));
+ 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);
}
diff --git a/lib/libc/rpc/authunix_prot.c b/lib/libc/rpc/authunix_prot.c
index 54f23fc9fefd..11bb74f8eb7f 100644
--- a/lib/libc/rpc/authunix_prot.c
+++ b/lib/libc/rpc/authunix_prot.c
@@ -1,3 +1,5 @@
+/* $NetBSD: authunix_prot.c,v 1.12 2000/01/22 22:19:17 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,10 +29,11 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
+static char *sccsid = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";
#endif
/*
@@ -40,29 +43,34 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "namespace.h"
+#include <assert.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
+#include "un-namespace.h"
/*
* XDR for unix authentication parameters.
*/
bool_t
xdr_authunix_parms(xdrs, p)
- register XDR *xdrs;
- register struct authunix_parms *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_int(xdrs, &(p->aup_uid))
&& xdr_int(xdrs, &(p->aup_gid))
&& xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
- &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
+ &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
return (TRUE);
}
return (FALSE);
}
-
diff --git a/lib/libc/rpc/bindresvport.3 b/lib/libc/rpc/bindresvport.3
index b71339822dc4..bfb011e0316a 100644
--- a/lib/libc/rpc/bindresvport.3
+++ b/lib/libc/rpc/bindresvport.3
@@ -1,14 +1,18 @@
.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
+.\" $NetBSD: bindresvport.3,v 1.8 2000/07/05 15:45:33 msaitoh Exp $
.\" $FreeBSD$
.\"
-.Dd January 27, 2000
+.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
+.Fd #include <sys/types.h>
.Fd #include <rpc/rpc.h>
.Ft int
.Fn bindresvport "int sd" "struct sockaddr_in *sin"
@@ -23,25 +27,38 @@ are used to bind a socket descriptor to a privileged
port, that is, a
port number in the range 0-1023.
.Pp
-Only root can bind to a privileged port; this call will fail for any
-other users.
-.Pp
-When
-.Va sin
-is not null,
-.Va sin->sin_family
+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
-.Va sd .
-If the value of sin->sin_port is non-zero
-.Fn bindresvport
-will attempt to use that specific port. If it fails, it chooses another
-privileged port automatically.
+.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
-It is legal to pass null pointer to
-.Va sin .
-In this case, the caller cannot get the port number
+If
+.Fa sin
+is the
+.Dv NULL
+pointer,
+an anonymous port will be allocated (as above).
+However, there is no way for
.Fn bindresvport
-has picked.
+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
@@ -57,50 +74,24 @@ sockets as well as
.Dv AF_INET
sockets.
.Sh RETURN VALUES
-.Fn bindresvport
-and
-.Fn bindresvport_sa
-return 0 if they are successful, otherwise \-1 is returned and
-.Va errno
-set to reflect the cause of the error.
+.Rv -std bindresvport
.Sh ERRORS
-The
-.Fn bindresvport
-and
-.Fn bindresvport_sa
-functions fail if:
.Bl -tag -width Er
-.It Bq Er EBADF
-.Fa sd
-is not a valid descriptor.
-.It Bq Er ENOTSOCK
-.Fa sd
-is not a socket.
-.It Bq Er EADDRNOTAVAIL
-The specified address is not available from the local machine.
-.It Bq Er EADDRINUSE
-The specified address is already in use.
-.It Bq Er EINVAL
-The socket is already bound to an address,
-or the socket family and the family of specified address mismatch.
-.It Bq Er EACCES
-The requested address is protected, and the current user
-has inadequate permission to access it.
-.It Bq Er EFAULT
-The
-.Fa name
-parameter is not in a valid part of the user
-address space.
-.It Bq Er ENOBUFS
-Insufficient resources were available in the system
-to perform the operation.
.It Bq Er EPFNOSUPPORT
-The protocol family has not been configured into the
-system, no implementation for it exists,
-or address family did not match between arguments.
+If second argument was supplied,
+and address family did not match between arguments.
.El
-.Sh "SEE ALSO"
+.Pp
+.Fn bindresvport
+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 socket 2 ,
-.Xr rresvport 3 ,
-.Xr rresvport_af 3
+.Xr getsockopt 2 ,
+.Xr setsockopt 2 ,
+.Xr ip 4
diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c
index 2aed9ddc48c8..43b2a4f3d8bc 100644
--- a/lib/libc/rpc/bindresvport.c
+++ b/lib/libc/rpc/bindresvport.c
@@ -1,3 +1,5 @@
+/* $NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/
@@ -42,10 +45,16 @@ static char *rcsid = "$FreeBSD$";
#include "namespace.h"
#include <sys/types.h>
-#include <sys/errno.h>
#include <sys/socket.h>
+
#include <netinet/in.h>
+
+#include <errno.h>
+#include <string.h>
#include <unistd.h>
+
+#include <rpc/rpc.h>
+
#include <string.h>
#include "un-namespace.h"
@@ -61,7 +70,7 @@ bindresvport(sd, sin)
}
/*
- * Bind a socket to a privileged port for whatever protocol.
+ * Bind a socket to a privileged IP port
*/
int
bindresvport_sa(sd, sa)
@@ -71,10 +80,12 @@ bindresvport_sa(sd, sa)
int old, error, af;
struct sockaddr_storage myaddr;
struct sockaddr_in *sin;
+#ifdef INET6
struct sockaddr_in6 *sin6;
+#endif
int proto, portrange, portlow;
- u_int16_t port;
- int salen;
+ u_int16_t *portp;
+ socklen_t salen;
if (sa == NULL) {
salen = sizeof(myaddr);
@@ -84,33 +95,38 @@ bindresvport_sa(sd, sa)
return -1; /* errno is correctly set */
af = sa->sa_family;
- memset(&myaddr, 0, salen);
+ memset(sa, 0, salen);
} else
af = sa->sa_family;
- if (af == AF_INET) {
+ 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);
- port = sin->sin_port;
- } else if (af == AF_INET6) {
+ portp = &sin->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
proto = IPPROTO_IPV6;
portrange = IPV6_PORTRANGE;
portlow = IPV6_PORTRANGE_LOW;
sin6 = (struct sockaddr_in6 *)sa;
salen = sizeof(struct sockaddr_in6);
- port = sin6->sin6_port;
- } else {
+ portp = &sin6->sin6_port;
+ break;
+#endif
+ default:
errno = EPFNOSUPPORT;
return (-1);
}
sa->sa_family = af;
sa->sa_len = salen;
- if (port == 0) {
- int oldlen = sizeof(old);
+ if (*portp == 0) {
+ socklen_t oldlen = sizeof(old);
error = _getsockopt(sd, proto, portrange, &old, &oldlen);
if (error < 0)
@@ -124,10 +140,10 @@ bindresvport_sa(sd, sa)
error = _bind(sd, sa, salen);
- if (port == 0) {
+ if (*portp == 0) {
int saved_errno = errno;
- if (error) {
+ if (error < 0) {
if (_setsockopt(sd, proto, portrange, &old,
sizeof(old)) < 0)
errno = saved_errno;
@@ -135,7 +151,7 @@ bindresvport_sa(sd, sa)
}
if (sa != (struct sockaddr *)&myaddr) {
- /* Hmm, what did the kernel assign... */
+ /* Hmm, what did the kernel assign? */
if (_getsockname(sd, sa, &salen) < 0)
errno = saved_errno;
return (error);
diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c
new file mode 100644
index 000000000000..f6f8641142a7
--- /dev/null
+++ b/lib/libc/rpc/clnt_bcast.c
@@ -0,0 +1,667 @@
+/* $NetBSD: clnt_bcast.c,v 1.3 2000/07/06 03:05:20 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)clnt_bcast.c 1.18 94/05/03 SMI" */
+
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro";
+#endif
+
+
+/*
+ * 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 "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/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 "un-namespace.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 */
+
+/*
+ * 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.
+ */
+
+struct broadif {
+ int index;
+ struct sockaddr_storage broadaddr;
+ TAILQ_ENTRY(broadif) link;
+};
+
+typedef TAILQ_HEAD(, broadif) broadlist_t;
+
+int __rpc_getbroadifs __P((int, int, int, broadlist_t *));
+void __rpc_freebroadifs __P((broadlist_t *));
+int __rpc_broadenable __P((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 (getifaddrs(&ifp) < 0)
+ return 0;
+
+ 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;
+#ifdef INET6
+ if ((af == AF_INET6 && !(ifap->ifa_flags & IFF_MULTICAST)) ||
+ !(ifap->ifa_flags & IFF_BROADCAST))
+ continue;
+#endif
+ bip = (struct broadif *)malloc(sizeof *bip);
+ if (bip == NULL)
+ break;
+ bip->index = if_nametoindex(ifap->ifa_name);
+#ifdef INET6
+ if (af != AF_INET6 && (ifap->ifa_flags & IFF_BROADCAST)) {
+#else
+ if (ifap->ifa_flags & IFF_BROADCAST) {
+#endif
+ memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
+ (size_t)ifap->ifa_broadaddr->sa_len);
+ sin = (struct sockaddr_in *)(void *)&bip->broadaddr;
+ sin->sin_port =
+ ((struct sockaddr_in *)
+ (void *)res->ai_addr)->sin_port;
+#ifdef INET6
+ } else if (af == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
+ inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
+ sin6->sin6_family = af;
+ sin6->sin6_len = sizeof *sin6;
+ sin6->sin6_port =
+ ((struct sockaddr_in6 *)
+ (void *)res->ai_addr)->sin6_port;
+ sin6->sin6_scope_id = bip->index;
+#endif
+ }
+ 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) < 0)
+ 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, outlen_pmap;
+ struct netconfig *nconf;
+ int msec;
+ int pollretval;
+ int fds_found;
+
+#ifdef PORTMAP
+ 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 < 0) {
+ 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) {
+ _close(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 (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 taddr, *np;
+ struct sockaddr_in *sin;
+
+#ifdef PORTMAP
+ if (pmap_flag && pmap_reply_flag) {
+ sin = (struct sockaddr_in *)
+ (void *)&fdlist[i].raddr;
+ sin->sin_port =
+ htons((u_short)port);
+ taddr.len = taddr.maxlen =
+ fdlist[i].raddr.ss_len;
+ 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)_close(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);
+}
diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c
new file mode 100644
index 000000000000..f9f56127eb4a
--- /dev/null
+++ b/lib/libc/rpc/clnt_dg.c
@@ -0,0 +1,821 @@
+/* $NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)clnt_dg.c 1.23 94/04/22 SMI" */
+
+#if 0
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+#endif
+
+/*
+ * Implements a connectionless client side RPC.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <rpc/rpc.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+
+#define RPC_MAX_BACKOFF 30 /* seconds */
+
+
+static struct clnt_ops *clnt_dg_ops __P((void));
+static bool_t time_not_ok __P((struct timeval *));
+static enum clnt_stat clnt_dg_call __P((CLIENT *, rpcproc_t, xdrproc_t, caddr_t,
+ xdrproc_t, caddr_t, struct timeval));
+static void clnt_dg_geterr __P((CLIENT *, struct rpc_err *));
+static bool_t clnt_dg_freeres __P((CLIENT *, xdrproc_t, caddr_t));
+static void clnt_dg_abort __P((CLIENT *));
+static bool_t clnt_dg_control __P((CLIENT *, u_int, char *));
+static void clnt_dg_destroy __P((CLIENT *));
+static int __rpc_timeval_to_msec __P((struct timeval *));
+
+
+
+
+/*
+ * 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;
+#define release_fd_lock(fd, mask) { \
+ mutex_lock(&clnt_fd_lock); \
+ if (__isthreaded) \
+ dg_fd_locks[fd] = 0; \
+ mutex_unlock(&clnt_fd_lock); \
+ thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \
+ cond_signal(&dg_cv[fd]); \
+}
+
+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 {
+ int 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 */
+ struct pollfd pfdp;
+ 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)
+ int 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;
+ sigset_t mask;
+ sigset_t newmask;
+ struct __rpc_sockinfo si;
+ int one = 1;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ 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;
+ (void) gettimeofday(&now, NULL);
+ call_msg.rm_xid = __RPC_GETXID(&now);
+ 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
+ _ioctl(fd, FIONBIO, (char *)(void *)&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;
+ cu->pfdp.fd = cu->cu_fd;
+ cu->pfdp.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
+ 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 */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t 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;
+ struct rpc_msg reply_msg;
+ XDR reply_xdrs;
+ struct timeval time_waited;
+ bool_t ok;
+ int nrefreshes = 2; /* number of times to refresh cred */
+ struct timeval timeout;
+ struct timeval retransmit_time;
+ struct timeval startime, curtime;
+ int firsttimeout = 1;
+ int dtbsize = __rpc_dtbsize();
+ sigset_t mask;
+ sigset_t newmask;
+ socklen_t fromlen, inlen;
+ ssize_t recvlen = 0;
+ int rpc_lock_value;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ dg_fd_locks[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 */
+ }
+
+ time_waited.tv_sec = 0;
+ time_waited.tv_usec = 0;
+ retransmit_time = cu->cu_wait;
+
+call_again:
+ xdrs = &(cu->cu_outxdrs);
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, cu->cu_xdrpos);
+ /*
+ * the transaction is the first thing in the out buffer
+ */
+ (*(u_int32_t *)(void *)(cu->cu_outbuf))++;
+ if ((! XDR_PUTINT32(xdrs, &proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+ }
+ outlen = (size_t)XDR_GETPOS(xdrs);
+
+send_again:
+ if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0,
+ (struct sockaddr *)(void *)&cu->cu_raddr, (socklen_t)cu->cu_rlen)
+ != outlen) {
+ cu->cu_error.re_errno = errno;
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ }
+
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ /*
+ * 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;
+
+
+ for (;;) {
+ switch (_poll(&cu->pfdp, 1,
+ __rpc_timeval_to_msec(&retransmit_time))) {
+ case 0:
+ time_waited.tv_sec += retransmit_time.tv_sec;
+ time_waited.tv_usec += retransmit_time.tv_usec;
+ while (time_waited.tv_usec >= 1000000) {
+ time_waited.tv_sec++;
+ time_waited.tv_usec -= 1000000;
+ }
+ /* update retransmit_time */
+ if (retransmit_time.tv_sec < RPC_MAX_BACKOFF) {
+ retransmit_time.tv_usec *= 2;
+ retransmit_time.tv_sec *= 2;
+ while (retransmit_time.tv_usec >= 1000000) {
+ retransmit_time.tv_sec++;
+ retransmit_time.tv_usec -= 1000000;
+ }
+ }
+
+ if ((time_waited.tv_sec < timeout.tv_sec) ||
+ ((time_waited.tv_sec == timeout.tv_sec) &&
+ (time_waited.tv_usec < timeout.tv_usec)))
+ goto send_again;
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+ case -1:
+ if (errno == EBADF) {
+ cu->cu_error.re_errno = errno;
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ if (errno != EINTR) {
+ errno = 0; /* reset it */
+ continue;
+ }
+ /* interrupted by another signal, update time_waited */
+ if (firsttimeout) {
+ /*
+ * Could have done gettimeofday before clnt_call
+ * but that means 1 more system call per each
+ * clnt_call, so do it after first time out
+ */
+ if (gettimeofday(&startime,
+ (struct timezone *) NULL) == -1) {
+ errno = 0;
+ continue;
+ }
+ firsttimeout = 0;
+ errno = 0;
+ continue;
+ };
+ if (gettimeofday(&curtime,
+ (struct timezone *) NULL) == -1) {
+ errno = 0;
+ continue;
+ };
+ time_waited.tv_sec += curtime.tv_sec - startime.tv_sec;
+ time_waited.tv_usec += curtime.tv_usec -
+ startime.tv_usec;
+ while (time_waited.tv_usec < 0) {
+ time_waited.tv_sec--;
+ time_waited.tv_usec += 1000000;
+ };
+ while (time_waited.tv_usec >= 1000000) {
+ time_waited.tv_sec++;
+ time_waited.tv_usec -= 1000000;
+ }
+ startime.tv_sec = curtime.tv_sec;
+ startime.tv_usec = curtime.tv_usec;
+ if ((time_waited.tv_sec > timeout.tv_sec) ||
+ ((time_waited.tv_sec == timeout.tv_sec) &&
+ (time_waited.tv_usec > timeout.tv_usec))) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ errno = 0; /* reset it */
+ continue;
+ };
+
+ if (cu->pfdp.revents & POLLNVAL || (cu->pfdp.revents == 0)) {
+ cu->cu_error.re_status = RPC_CANTRECV;
+ /*
+ * Note: we're faking errno here because we
+ * previously would have expected _poll() to
+ * return -1 with errno EBADF. Poll(BA_OS)
+ * returns 0 and sets the POLLNVAL revents flag
+ * instead.
+ */
+ cu->cu_error.re_errno = errno = EBADF;
+ release_fd_lock(cu->cu_fd, mask);
+ return (-1);
+ }
+
+ /* We have some data now */
+ do {
+ if (errno == EINTR) {
+ /*
+ * Must make sure errno was not already
+ * EINTR in case _recvfrom() returns -1.
+ */
+ errno = 0;
+ }
+ fromlen = sizeof (struct sockaddr_storage);
+ recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf,
+ cu->cu_recvsz, 0, (struct sockaddr *)(void *)&cu->cu_raddr,
+ &fromlen);
+ } while (recvlen < 0 && errno == EINTR);
+ if (recvlen < 0) {
+ if (errno == EWOULDBLOCK)
+ continue;
+ cu->cu_error.re_errno = errno;
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ if (recvlen < sizeof (u_int32_t))
+ continue;
+ /* see if reply transaction id matches sent id */
+ if (*((u_int32_t *)(void *)(cu->cu_inbuf)) !=
+ *((u_int32_t *)(void *)(cu->cu_outbuf)))
+ continue;
+ /* we now assume we have the proper reply */
+ break;
+ }
+ inlen = (socklen_t)recvlen;
+
+ /*
+ * now decode and validate the response
+ */
+
+ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, 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;
+
+ }
+ 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;
+ caddr_t res_ptr;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ XDR *xdrs = &(cu->cu_outxdrs);
+ bool_t dummy;
+ sigset_t mask;
+ sigset_t newmask;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[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[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;
+ char *info;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ struct netbuf *addr;
+ sigset_t mask;
+ sigset_t newmask;
+ int rpc_lock_value;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ dg_fd_locks[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 *)(void *)info)) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ cu->cu_total = *(struct timeval *)(void *)info;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)(void *)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 *)(void *)info)) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ cu->cu_wait = *(struct timeval *)(void *)info;
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ *(struct timeval *)(void *)info = cu->cu_wait;
+ break;
+ case CLGET_FD:
+ *(int *)(void *)info = cu->cu_fd;
+ break;
+ case CLGET_SVC_ADDR:
+ addr = (struct netbuf *)(void *)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 *)(void *)info;
+ if (addr->len < sizeof cu->cu_raddr)
+ 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 *)(void *)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 *)(void *)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 *)(void *)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 *)(void *)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 *)(void *)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 *)(void *)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;
+ int cu_fd = cu->cu_fd;
+ sigset_t mask;
+ sigset_t newmask;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu_fd])
+ cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
+ if (cu->cu_closeit)
+ (void)_close(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[cu_fd]);
+}
+
+static struct clnt_ops *
+clnt_dg_ops()
+{
+ static struct clnt_ops ops;
+ extern mutex_t ops_lock;
+ sigset_t mask;
+ sigset_t newmask;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ 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);
+}
+
+
+/*
+ * Convert from timevals (used by select) to milliseconds (used by poll).
+ */
+static int
+__rpc_timeval_to_msec(t)
+ struct timeval *t;
+{
+ int t1, tmp;
+
+ /*
+ * We're really returning t->tv_sec * 1000 + (t->tv_usec / 1000)
+ * but try to do so efficiently. Note: 1000 = 1024 - 16 - 8.
+ */
+ tmp = (int)t->tv_sec << 3;
+ t1 = -tmp;
+ t1 += t1 << 1;
+ t1 += tmp << 7;
+ if (t->tv_usec)
+ t1 += (int)(t->tv_usec / 1000);
+
+ return (t1);
+}
diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c
index d885f1820d17..696ea541a2ed 100644
--- a/lib/libc/rpc/clnt_generic.c
+++ b/lib/libc/rpc/clnt_generic.c
@@ -1,3 +1,5 @@
+/* $NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,8 @@
* Mountain View, California 94043
*/
+/* #ident "@(#)clnt_generic.c 1.20 94/05/03 SMI" */
+
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
/*static char *sccsid = "from: @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC";*/
@@ -34,104 +38,312 @@ static char *rcsid = "$FreeBSD$";
#endif
/*
- * Copyright (C) 1987, Sun Microsystems, Inc.
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
-#include <rpc/rpc.h>
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
#include <errno.h>
#include <netdb.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+/*
+ * 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.
+ */
+CLIENT *
+clnt_create_vers(hostname, prog, vers_out, vers_low, vers_high, nettype)
+ const char *hostname;
+ rpcprog_t prog;
+ rpcvers_t *vers_out;
+ rpcvers_t vers_low;
+ rpcvers_t vers_high;
+ const char *nettype;
+{
+ CLIENT *clnt;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ struct rpc_err rpcerr;
+
+ clnt = clnt_create(hostname, prog, vers_high, nettype);
+ 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);
+ }
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ unsigned long minvers, maxvers;
+
+ clnt_geterr(clnt, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ if (maxvers < vers_high)
+ vers_high = (rpcvers_t)maxvers;
+ if (minvers > vers_low)
+ vers_low = (rpcvers_t)minvers;
+ if (vers_low > vers_high) {
+ goto error;
+ }
+ CLNT_CONTROL(clnt, CLSET_VERS, (char *)(void *)&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);
+}
/*
- * Generic client creation: takes (hostname, program-number, protocol) and
+ * 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_tp_create();
*/
CLIENT *
-clnt_create(hostname, prog, vers, proto)
- char *hostname;
- u_long prog;
- u_long vers;
- char *proto;
+clnt_create(hostname, prog, vers, nettype)
+ const char *hostname; /* server name */
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ const char *nettype; /* net type */
{
- struct hostent *h;
- struct protoent *p;
- struct sockaddr_in sin;
- struct sockaddr_un sun;
- int sock;
- static struct timeval tv;
- CLIENT *client;
-
- if (!strcmp(proto, "unix")) {
- bzero((char *)&sun, sizeof(sun));
- sun.sun_family = AF_UNIX;
- strcpy(sun.sun_path, hostname);
- sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) +
- strlen(sun.sun_path) + 1;
- sock = RPC_ANYSOCK;
- client = clntunix_create(&sun, prog, vers, &sock, 0, 0);
- if (client == NULL)
- return(NULL);
- tv.tv_sec = 25;
- tv.tv_usec = 0;
- clnt_control(client, CLSET_TIMEOUT, &tv);
- return(client);
- }
+ struct netconfig *nconf;
+ CLIENT *clnt = NULL;
+ void *handle;
+ enum clnt_stat save_cf_stat = RPC_SUCCESS;
+ struct rpc_err save_cf_error;
- h = gethostbyname(hostname);
- if (h == NULL) {
- rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
- if (h->h_addrtype != AF_INET) {
- /*
- * Only support INET for now
- */
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
- 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(hostname, prog, vers, nconf);
+ 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).
+ */
+ if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE) {
+ 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''
+ */
+ if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE) &&
+ (save_cf_stat != RPC_SUCCESS)) {
+ rpc_createerr.cf_stat = save_cf_stat;
+ rpc_createerr.cf_error = save_cf_error;
}
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_family = h->h_addrtype;
- sin.sin_port = 0;
- memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length);
- p = getprotobyname(proto);
- if (p == NULL) {
+ __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()
+ */
+CLIENT *
+clnt_tp_create(hostname, prog, vers, nconf)
+ const char *hostname; /* server name */
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ const struct netconfig *nconf; /* net config struct */
+{
+ struct netbuf *svcaddr; /* servers address */
+ CLIENT *cl = NULL; /* client handle */
+
+ if (nconf == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
- rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
return (NULL);
}
- sock = RPC_ANYSOCK;
- switch (p->p_proto) {
- case IPPROTO_UDP:
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- client = clntudp_create(&sin, prog, vers, tv, &sock);
- if (client == NULL) {
- return (NULL);
+
+ /*
+ * Get the address of the server
+ */
+ if ((svcaddr = __rpcb_findaddr(prog, vers, nconf, hostname,
+ &cl)) == 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);
+ } 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);
}
-#if 0 /* XXX do we need this? */
- tv.tv_sec = 25;
- tv.tv_usec = 0;
- clnt_control(client, CLSET_TIMEOUT, &tv);
-#endif
- break;
- case IPPROTO_TCP:
- client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
- if (client == 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(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
+ int fd; /* fd */
+ const struct netconfig *nconf; /* netconfig structure */
+ const struct netbuf *svcaddr; /* servers address */
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ u_int sendsz; /* send size */
+ u_int recvsz; /* recv size */
+{
+ CLIENT *cl; /* client handle */
+ bool_t madefd = FALSE; /* whether fd opened here */
+ long servtype;
+ int one = 1;
+ struct __rpc_sockinfo si;
+
+ if (fd == RPC_ANYFD) {
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
return (NULL);
}
-#if 0 /* XXX do we need this? */
- tv.tv_sec = 25;
- tv.tv_usec = 0;
- clnt_control(client, CLSET_TIMEOUT, &tv);
-#endif
+
+ fd = __rpc_nconf2fd(nconf);
+
+ if (fd == -1)
+ goto err;
+
+ madefd = TRUE;
+ servtype = nconf->nc_semantics;
+ if (!__rpc_fd2sockinfo(fd, &si))
+ goto err;
+
+ bindresvport(fd, NULL);
+ } 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_ORD:
+ cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
+ if (!nconf || !cl)
+ break;
+ /* XXX fvdl - is this useful? */
+ if (strncmp(nconf->nc_protofmly, "inet", 4) == 0)
+ _setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
+ sizeof (one));
+ break;
+ case NC_TPI_CLTS:
+ cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
break;
default:
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
- return (NULL);
+ goto err;
}
- return (client);
+
+ 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, (char *) NULL); */
+ };
+
+ return (cl);
+
+err:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+err1: if (madefd)
+ (void)_close(fd);
+ return (NULL);
}
diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c
index 331f52b04496..6ddf39d98347 100644
--- a/lib/libc/rpc/clnt_perror.c
+++ b/lib/libc/rpc/clnt_perror.c
@@ -1,3 +1,6 @@
+/* $NetBSD: clnt_perror.c,v 1.24 2000/06/02 23:11:07 fvdl Exp $ */
+
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +30,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -39,19 +43,24 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
+#include "namespace.h"
+#include <assert.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 *auth_errmsg();
-#define CLNT_PERROR_BUFLEN 256
+#include "un-namespace.h"
static char *buf;
+static char *_buf __P((void));
+static char *auth_errmsg __P((enum auth_stat));
+#define CLNT_PERROR_BUFLEN 256
+
static char *
_buf()
{
@@ -67,19 +76,32 @@ _buf()
char *
clnt_sperror(rpch, s)
CLIENT *rpch;
- char *s;
+ const char *s;
{
struct rpc_err e;
char *err;
- char *str = _buf();
- char *strstart = str;
+ char *str;
+ char *strstart;
+ size_t len, i;
+
+ assert(rpch != NULL);
+ assert(s != NULL);
+ str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
if (str == 0)
return (0);
+ len = CLNT_PERROR_BUFLEN;
+ strstart = str;
CLNT_GETERR(rpch, &e);
- (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s", s, clnt_sperrno(e.re_status));
- str += strlen(str);
+ i = snprintf(str, len, "%s: ", s);
+ 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:
@@ -99,42 +121,48 @@ clnt_sperror(rpch, s)
case RPC_CANTSEND:
case RPC_CANTRECV:
- (void) snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart),
- "; errno = %s\n", strerror(e.re_errno));
+ i = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
+ str += i;
+ len -= i;
break;
case RPC_VERSMISMATCH:
- (void) sprintf(str,
- "; low version = %lu, high version = %lu\n",
- (u_long)e.re_vers.low, (u_long)e.re_vers.high);
+ i = snprintf(str, len, "; low version = %u, high version = %u",
+ e.re_vers.low, e.re_vers.high);
+ str += i;
+ len -= i;
break;
case RPC_AUTHERROR:
err = auth_errmsg(e.re_why);
- (void) sprintf(str,"; why = ");
- str += strlen(str);
+ i = snprintf(str, len, "; why = ");
+ str += i;
+ len -= i;
if (err != NULL) {
- (void) sprintf(str, "%s\n",err);
+ i = snprintf(str, len, "%s",err);
} else {
- (void) sprintf(str,
- "(unknown authentication error - %d)\n",
+ i = snprintf(str, len,
+ "(unknown authentication error - %d)",
(int) e.re_why);
}
+ str += i;
+ len -= i;
break;
case RPC_PROGVERSMISMATCH:
- (void) sprintf(str,
- "; low version = %lu, high version = %lu\n",
- (u_long)e.re_vers.low, (u_long)e.re_vers.high);
+ i = snprintf(str, len, "; low version = %u, high version = %u",
+ e.re_vers.low, e.re_vers.high);
+ str += i;
+ len -= i;
break;
default: /* unknown */
- (void) sprintf(str,
- "; s1 = %lu, s2 = %lu\n",
- (long)e.re_lb.s1, (long)e.re_lb.s2);
+ i = snprintf(str, len, "; s1 = %u, s2 = %u",
+ e.re_lb.s1, e.re_lb.s2);
+ str += i;
+ len -= i;
break;
}
- strstart[CLNT_PERROR_BUFLEN-2] = '\n';
strstart[CLNT_PERROR_BUFLEN-1] = '\0';
return(strstart) ;
}
@@ -142,11 +170,14 @@ clnt_sperror(rpch, s)
void
clnt_perror(rpch, s)
CLIENT *rpch;
- char *s;
+ const char *s;
{
- (void) fprintf(stderr,"%s\n",clnt_sperror(rpch,s));
-}
+ assert(rpch != NULL);
+ assert(s != NULL);
+
+ (void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
+}
static const char *const rpc_errlist[] = {
"RPC: Success", /* 0 - RPC_SUCCESS */
@@ -180,6 +211,7 @@ clnt_sperrno(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)");
@@ -189,53 +221,78 @@ void
clnt_perrno(num)
enum clnt_stat num;
{
- (void) fprintf(stderr,"%s\n",clnt_sperrno(num));
+ (void) fprintf(stderr, "%s\n", clnt_sperrno(num));
}
char *
clnt_spcreateerror(s)
- char *s;
+ const char *s;
{
- char *str = _buf();
+ char *str;
+ size_t len, i;
+ assert(s != NULL);
+
+ str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
if (str == 0)
return(0);
+ len = CLNT_PERROR_BUFLEN;
+ i = snprintf(str, len, "%s: ", s);
+ len -= i;
+ (void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
switch (rpc_createerr.cf_stat) {
case RPC_PMAPFAILURE:
- (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
- clnt_sperrno(rpc_createerr.cf_stat),
- clnt_sperrno(rpc_createerr.cf_error.re_status));
+ (void) strncat(str, " - ", len - 1);
+ (void) strncat(str,
+ clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
break;
case RPC_SYSTEMERROR:
- (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
- clnt_sperrno(rpc_createerr.cf_stat),
- strerror(rpc_createerr.cf_error.re_errno));
+ (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:
- (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s\n", s,
- clnt_sperrno(rpc_createerr.cf_stat));
break;
}
- str[CLNT_PERROR_BUFLEN-2] = '\n';
str[CLNT_PERROR_BUFLEN-1] = '\0';
return (str);
}
void
clnt_pcreateerror(s)
- char *s;
+ const char *s;
{
- (void) fprintf(stderr,"%s\n",clnt_spcreateerror(s));
+
+ assert(s != NULL);
+
+ (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 */
+ "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 */
@@ -248,6 +305,7 @@ auth_errmsg(stat)
unsigned int errnum = stat;
if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
+ /* LINTED interface problem */
return (char *)auth_errlist[errnum];
return(NULL);
diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c
index 6f228fe99d69..01dfc7997d0a 100644
--- a/lib/libc/rpc/clnt_raw.c
+++ b/lib/libc/rpc/clnt_raw.c
@@ -1,3 +1,5 @@
+/* $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *sccsid = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -44,9 +47,18 @@ static char *rcsid = "$FreeBSD$";
* any interference from the kernal.
*/
-#include <rpc/rpc.h>
-#include <stdlib.h>
+#include "reentrant.h"
+#include "namespace.h"
+#include <assert.h>
+#include <err.h>
#include <stdio.h>
+#include <stdlib.h>
+
+#include <rpc/rpc.h>
+#include <rpc/raw.h>
+#include "un-namespace.h"
+
+extern mutex_t clntraw_lock;
#define MCALL_MSG_SIZE 24
@@ -56,46 +68,47 @@ static char *rcsid = "$FreeBSD$";
static struct clntraw_private {
CLIENT client_object;
XDR xdr_stream;
- char _raw_buf[UDPMSGSIZE];
- char mashl_callmsg[MCALL_MSG_SIZE];
+ 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 clntraw_call();
-static void clntraw_abort();
-static void clntraw_geterr();
-static bool_t clntraw_freeres();
-static bool_t clntraw_control();
-static void clntraw_destroy();
-
-static struct clnt_ops client_ops = {
- clntraw_call,
- clntraw_abort,
- clntraw_geterr,
- clntraw_freeres,
- clntraw_destroy,
- clntraw_control
-};
-
-void svc_getreq();
+static enum clnt_stat clnt_raw_call __P((CLIENT *, rpcproc_t, xdrproc_t,
+ caddr_t, xdrproc_t, caddr_t, struct timeval));
+static void clnt_raw_geterr __P((CLIENT *, struct rpc_err *));
+static bool_t clnt_raw_freeres __P((CLIENT *, xdrproc_t, caddr_t));
+static void clnt_raw_abort __P((CLIENT *));
+static bool_t clnt_raw_control __P((CLIENT *, u_int, char *));
+static void clnt_raw_destroy __P((CLIENT *));
+static struct clnt_ops *clnt_raw_ops __P((void));
/*
* Create a client handle for memory based rpc.
*/
CLIENT *
-clntraw_create(prog, vers)
- u_long prog;
- u_long vers;
+clnt_raw_create(prog, vers)
+ rpcprog_t prog;
+ rpcvers_t vers;
{
- register struct clntraw_private *clp = clntraw_private;
+ struct clntraw_private *clp = clntraw_private;
struct rpc_msg call_msg;
XDR *xdrs = &clp->xdr_stream;
CLIENT *client = &clp->client_object;
- if (clp == 0) {
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
- if (clp == 0)
- return (0);
+ 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;
}
/*
@@ -103,12 +116,12 @@ clntraw_create(prog, vers)
*/
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- call_msg.rm_call.cb_prog = prog;
- call_msg.rm_call.cb_vers = vers;
- xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
- if (! xdr_callhdr(xdrs, &call_msg)) {
- perror("clnt_raw.c - Fatal header serialization error.");
- }
+ /* 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);
@@ -120,38 +133,47 @@ clntraw_create(prog, vers)
/*
* create client handle
*/
- client->cl_ops = &client_ops;
+ client->cl_ops = clnt_raw_ops();
client->cl_auth = authnone_create();
+ mutex_unlock(&clntraw_lock);
return (client);
}
-static enum clnt_stat
-clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+/* ARGSUSED */
+static enum clnt_stat
+clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
CLIENT *h;
- u_long proc;
+ rpcproc_t proc;
xdrproc_t xargs;
caddr_t argsp;
xdrproc_t xresults;
caddr_t resultsp;
struct timeval timeout;
{
- register struct clntraw_private *clp = clntraw_private;
- register XDR *xdrs = &clp->xdr_stream;
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
struct rpc_msg msg;
enum clnt_stat status;
struct rpc_err error;
- if (clp == 0)
+ 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);
- ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
- if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
- (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ clp->u.mashl_rpcmsg.rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp))) {
return (RPC_CANTENCODEARGS);
@@ -162,7 +184,7 @@ call_again:
* We have to call server input routine here because this is
* all going on in one process. Yuk.
*/
- svc_getreq(1);
+ svc_getreq_common(FD_SETSIZE);
/*
* get results
@@ -172,8 +194,23 @@ call_again:
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))
+ 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;
@@ -183,7 +220,7 @@ call_again:
}
} /* end successful completion */
else {
- if (AUTH_REFRESH(h->cl_auth))
+ if (AUTH_REFRESH(h->cl_auth, &msg))
goto call_again;
} /* end of unsuccessful completion */
@@ -200,43 +237,78 @@ call_again:
return (status);
}
+/*ARGSUSED*/
static void
-clntraw_geterr()
+clnt_raw_geterr(cl, err)
+ CLIENT *cl;
+ struct rpc_err *err;
{
}
+/* ARGSUSED */
static bool_t
-clntraw_freeres(cl, xdr_res, res_ptr)
+clnt_raw_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
- register struct clntraw_private *clp = clntraw_private;
- register XDR *xdrs = &clp->xdr_stream;
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
bool_t rval;
- if (clp == 0)
- {
+ 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
-clntraw_abort()
+clnt_raw_abort(cl)
+ CLIENT *cl;
{
}
+/*ARGSUSED*/
static bool_t
-clntraw_control()
+clnt_raw_control(cl, ui, str)
+ CLIENT *cl;
+ u_int ui;
+ char *str;
{
return (FALSE);
}
+/*ARGSUSED*/
static void
-clntraw_destroy()
+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);
+}
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c
index 46d959b22011..09b65fc0b0d0 100644
--- a/lib/libc/rpc/clnt_simple.c
+++ b/lib/libc/rpc/clnt_simple.c
@@ -1,3 +1,5 @@
+/* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,6 +28,9 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/
@@ -35,90 +40,156 @@ static char *rcsid = "$FreeBSD$";
/*
* clnt_simple.c
- * Simplified front end to rpc.
+ * Simplified front end to client rpc.
*
- * Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "reentrant.h"
#include "namespace.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 <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <netdb.h>
#include "un-namespace.h"
-static struct callrpc_private {
- CLIENT *client;
- int socket;
- int oldprognum, oldversnum, valid;
- char *oldhost;
-} *callrpc_private;
+#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 struct rpc_call_private *rpc_call_private_main;
-int
-callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
- char *host;
- int prognum, versnum, procnum;
- xdrproc_t inproc, outproc;
- char *in, *out;
+static void rpc_call_destroy __P((void *));
+
+static void
+rpc_call_destroy(void *vp)
{
- register struct callrpc_private *crp = callrpc_private;
- struct sockaddr_in server_addr;
+ 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 hostent *hp;
struct timeval timeout, tottimeout;
+ static thread_key_t rpc_call_key;
+ extern mutex_t tsd_lock;
+ int main_thread = 1;
- if (crp == 0) {
- crp = (struct callrpc_private *)calloc(1, sizeof (*crp));
- if (crp == 0)
- return (0);
- callrpc_private = crp;
+ if ((main_thread = thr_main())) {
+ rcp = rpc_call_private_main;
+ } else {
+ if (rpc_call_key == 0) {
+ mutex_lock(&tsd_lock);
+ if (rpc_call_key == 0)
+ thr_keycreate(&rpc_call_key, rpc_call_destroy);
+ mutex_unlock(&tsd_lock);
+ }
+ rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
}
- if (crp->oldhost == NULL) {
- crp->oldhost = malloc(MAXHOSTNAMELEN);
- crp->oldhost[0] = 0;
- crp->socket = RPC_ANYSOCK;
+ 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);
+ }
+ if (main_thread)
+ rpc_call_private_main = rcp;
+ else
+ thr_setspecific(rpc_call_key, (void *) rcp);
+ rcp->valid = 0;
+ rcp->client = NULL;
}
- if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
- && strcmp(crp->oldhost, host) == 0) {
- /* reuse old client */
- } else {
- crp->valid = 0;
- if (crp->socket != -1)
- (void)_close(crp->socket);
- crp->socket = RPC_ANYSOCK;
- if (crp->client) {
- clnt_destroy(crp->client);
- crp->client = NULL;
+ if ((nettype == NULL) || (nettype[0] == NULL))
+ 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);
}
- if ((hp = gethostbyname(host)) == NULL)
- return ((int) RPC_UNKNOWNHOST);
+ /*
+ * 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;
- memset(&server_addr, 0, sizeof(server_addr));
- memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
- server_addr.sin_len = sizeof(struct sockaddr_in);
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = 0;
- if ((crp->client = clntudp_create(&server_addr, (u_long)prognum,
- (u_long)versnum, timeout, &crp->socket)) == NULL)
- return ((int) rpc_createerr.cf_stat);
- crp->valid = 1;
- crp->oldprognum = prognum;
- crp->oldversnum = versnum;
- (void) strcpy(crp->oldhost, host);
- }
+ (void) CLNT_CONTROL(rcp->client,
+ CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
+ if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
+ _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;
- clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+ /*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)
- crp->valid = 0;
- return ((int) clnt_stat);
+ rcp->valid = 0;
+ return (clnt_stat);
}
diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c
deleted file mode 100644
index 9e8e3948d26b..000000000000
--- a/lib/libc/rpc/clnt_tcp.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- *
- * TCP based RPC supports 'batched calls'.
- * A sequence of calls may be batched-up in a send buffer. The rpc call
- * return immediately to the client even though the call was not necessarily
- * sent. The batching occurs if the results' xdr routine is NULL (0) AND
- * the rpc timeout value is zero (see clnt.h, rpc).
- *
- * Clients should NOT casually batch calls that in fact return results; that is,
- * the server side should be aware that a call is batched and not produce any
- * return message. Batched calls that produce many result messages can
- * deadlock (netlock) the client and the server....
- *
- * Now go hang yourself.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <errno.h>
-#include <rpc/pmap_clnt.h>
-#include "un-namespace.h"
-
-#define MCALL_MSG_SIZE 24
-
-static int readtcp();
-static int writetcp();
-
-static enum clnt_stat clnttcp_call();
-static void clnttcp_abort();
-static void clnttcp_geterr();
-static bool_t clnttcp_freeres();
-static bool_t clnttcp_control();
-static void clnttcp_destroy();
-
-static struct clnt_ops tcp_ops = {
- clnttcp_call,
- clnttcp_abort,
- clnttcp_geterr,
- clnttcp_freeres,
- clnttcp_destroy,
- clnttcp_control
-};
-
-struct ct_data {
- int ct_sock;
- bool_t ct_closeit;
- struct timeval ct_wait;
- bool_t ct_waitset; /* wait set by clnt_control? */
- struct sockaddr_in ct_addr;
- struct rpc_err ct_error;
- char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
- u_int ct_mpos; /* pos after marshal */
- XDR ct_xdrs;
-};
-
-/*
- * Create a client handle for a tcp/ip connection.
- * If *sockp<0, *sockp is set to a newly created TCP socket and it is
- * connected to raddr. If *sockp non-negative then
- * raddr is ignored. The rpc/tcp package does buffering
- * similar to stdio, so the client must pick send and receive buffer sizes,];
- * 0 => use the default.
- * If raddr->sin_port is 0, then a binder on the remote machine is
- * consulted for the right port number.
- * NB: *sockp is copied into a private area.
- * NB: It is the clients responsibility to close *sockp.
- * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
- * something more useful.
- */
-CLIENT *
-clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
- struct sockaddr_in *raddr;
- u_long prog;
- u_long vers;
- register int *sockp;
- u_int sendsz;
- u_int recvsz;
-{
- CLIENT *h;
- register struct ct_data *ct = NULL;
- struct timeval now;
- struct rpc_msg call_msg;
- static u_int32_t disrupt;
-
- if (disrupt == 0)
- disrupt = (u_int32_t)(long)raddr;
-
- h = (CLIENT *)mem_alloc(sizeof(*h));
- if (h == NULL) {
- (void)fprintf(stderr, "clnttcp_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
- ct = (struct ct_data *)mem_alloc(sizeof(*ct));
- if (ct == NULL) {
- (void)fprintf(stderr, "clnttcp_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
-
- /*
- * If no port number given ask the pmap for one
- */
- if (raddr->sin_port == 0) {
- u_short port;
- if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
- mem_free((caddr_t)ct, sizeof(struct ct_data));
- mem_free((caddr_t)h, sizeof(CLIENT));
- return ((CLIENT *)NULL);
- }
- raddr->sin_port = htons(port);
- }
-
- /*
- * If no socket given, open one
- */
- if (*sockp < 0) {
- *sockp = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- (void)bindresvport(*sockp, (struct sockaddr_in *)0);
- if ((*sockp < 0)
- || (_connect(*sockp, (struct sockaddr *)raddr,
- sizeof(*raddr)) < 0)) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- if (*sockp != -1)
- (void)_close(*sockp);
- goto fooy;
- }
- ct->ct_closeit = TRUE;
- } else {
- ct->ct_closeit = FALSE;
- }
-
- /*
- * Set up private data struct
- */
- ct->ct_sock = *sockp;
- ct->ct_wait.tv_usec = 0;
- ct->ct_waitset = FALSE;
- ct->ct_addr = *raddr;
-
- /*
- * Initialize call message
- */
- (void)gettimeofday(&now, (struct timezone *)0);
- call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
- call_msg.rm_direction = CALL;
- call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- call_msg.rm_call.cb_prog = prog;
- call_msg.rm_call.cb_vers = vers;
-
- /*
- * pre-serialize the static part of the call msg and stash it away
- */
- xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
- XDR_ENCODE);
- if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
- if (ct->ct_closeit) {
- (void)_close(*sockp);
- }
- goto fooy;
- }
- ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
- XDR_DESTROY(&(ct->ct_xdrs));
-
- /*
- * Create a client handle which uses xdrrec for serialization
- * and authnone for authentication.
- */
- xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
- (caddr_t)ct, readtcp, writetcp);
- h->cl_ops = &tcp_ops;
- h->cl_private = (caddr_t) ct;
- h->cl_auth = authnone_create();
- return (h);
-
-fooy:
- /*
- * Something goofed, free stuff and barf
- */
- if (ct)
- mem_free((caddr_t)ct, sizeof(struct ct_data));
- if (h)
- mem_free((caddr_t)h, sizeof(CLIENT));
- return ((CLIENT *)NULL);
-}
-
-static enum clnt_stat
-clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
- register CLIENT *h;
- u_long proc;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
- xdrproc_t xdr_results;
- caddr_t results_ptr;
- struct timeval timeout;
-{
- register struct ct_data *ct = (struct ct_data *) h->cl_private;
- register XDR *xdrs = &(ct->ct_xdrs);
- struct rpc_msg reply_msg;
- u_long x_id;
- u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
- register bool_t shipnow;
- int refreshes = 2;
-
- if (!ct->ct_waitset) {
- ct->ct_wait = timeout;
- }
-
- shipnow =
- (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
- && timeout.tv_usec == 0) ? FALSE : TRUE;
-
-call_again:
- xdrs->x_op = XDR_ENCODE;
- ct->ct_error.re_status = RPC_SUCCESS;
- x_id = ntohl(--(*msg_x_id));
- if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
- (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
- (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
- (! (*xdr_args)(xdrs, args_ptr))) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- ct->ct_error.re_status = RPC_CANTENCODEARGS;
- (void)xdrrec_endofrecord(xdrs, TRUE);
- return (ct->ct_error.re_status);
- }
- if (! xdrrec_endofrecord(xdrs, shipnow))
- return (ct->ct_error.re_status = RPC_CANTSEND);
- if (! shipnow)
- return (RPC_SUCCESS);
- /*
- * Hack to provide rpc-based message passing
- */
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
- return(ct->ct_error.re_status = RPC_TIMEDOUT);
- }
-
-
- /*
- * Keep receiving until we get a valid transaction id
- */
- xdrs->x_op = XDR_DECODE;
- while (TRUE) {
- reply_msg.acpted_rply.ar_verf = _null_auth;
- reply_msg.acpted_rply.ar_results.where = NULL;
- reply_msg.acpted_rply.ar_results.proc = xdr_void;
- if (! xdrrec_skiprecord(xdrs))
- return (ct->ct_error.re_status);
- /* now decode and validate the response header */
- if (! xdr_replymsg(xdrs, &reply_msg)) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- continue;
- return (ct->ct_error.re_status);
- }
- if (reply_msg.rm_xid == x_id)
- break;
- }
-
- /*
- * process header
- */
- _seterr_reply(&reply_msg, &(ct->ct_error));
- if (ct->ct_error.re_status == RPC_SUCCESS) {
- if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
- ct->ct_error.re_status = RPC_AUTHERROR;
- ct->ct_error.re_why = AUTH_INVALIDRESP;
- } else if (! (*xdr_results)(xdrs, results_ptr)) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- ct->ct_error.re_status = RPC_CANTDECODERES;
- }
- /* free verifier ... */
- 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 */
- else {
- /* maybe our credentials need to be refreshed ... */
- if (refreshes-- && AUTH_REFRESH(h->cl_auth))
- goto call_again;
- } /* end of unsuccessful completion */
- return (ct->ct_error.re_status);
-}
-
-static void
-clnttcp_geterr(h, errp)
- CLIENT *h;
- struct rpc_err *errp;
-{
- register struct ct_data *ct =
- (struct ct_data *) h->cl_private;
-
- *errp = ct->ct_error;
-}
-
-static bool_t
-clnttcp_freeres(cl, xdr_res, res_ptr)
- CLIENT *cl;
- xdrproc_t xdr_res;
- caddr_t res_ptr;
-{
- register struct ct_data *ct = (struct ct_data *)cl->cl_private;
- register XDR *xdrs = &(ct->ct_xdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_res)(xdrs, res_ptr));
-}
-
-static void
-clnttcp_abort()
-{
-}
-
-
-static bool_t
-clnttcp_control(cl, request, info)
- CLIENT *cl;
- int request;
- char *info;
-{
- register struct ct_data *ct = (struct ct_data *)cl->cl_private;
- register struct timeval *tv;
- int len;
-
- switch (request) {
- case CLSET_FD_CLOSE:
- ct->ct_closeit = TRUE;
- break;
- case CLSET_FD_NCLOSE:
- ct->ct_closeit = FALSE;
- break;
- case CLSET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- tv = (struct timeval *)info;
- ct->ct_wait.tv_sec = tv->tv_sec;
- ct->ct_wait.tv_usec = tv->tv_usec;
- ct->ct_waitset = TRUE;
- break;
- case CLGET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- *(struct timeval *)info = ct->ct_wait;
- break;
- case CLGET_SERVER_ADDR:
- if (info == NULL)
- return(FALSE);
- *(struct sockaddr_in *)info = ct->ct_addr;
- break;
- case CLGET_FD:
- if (info == NULL)
- return(FALSE);
- *(int *)info = ct->ct_sock;
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
- break;
- case CLSET_XID:
- /* This will set the xid of the NEXT call */
- if (info == NULL)
- return(FALSE);
- *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
- /* decrement by 1 as clnttcp_call() increments once */
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
- 4 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_VERS:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_PROG:
- /*
- * This RELIES on the information that, in the call body,
- * the program number field is the field from the
- * begining of the RPC header. MUST be changed if the
- * call_struct is changed
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
- 3 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_PROG:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_LOCAL_ADDR:
- len = sizeof(struct sockaddr);
- if (_getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
- return(FALSE);
- break;
- case CLGET_RETRY_TIMEOUT:
- case CLSET_RETRY_TIMEOUT:
- case CLGET_SVC_ADDR:
- case CLSET_SVC_ADDR:
- case CLSET_PUSH_TIMOD:
- case CLSET_POP_TIMOD:
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-
-static void
-clnttcp_destroy(h)
- CLIENT *h;
-{
- register struct ct_data *ct =
- (struct ct_data *) h->cl_private;
-
- if (ct->ct_closeit) {
- (void)_close(ct->ct_sock);
- }
- XDR_DESTROY(&(ct->ct_xdrs));
- mem_free((caddr_t)ct, sizeof(struct ct_data));
- mem_free((caddr_t)h, sizeof(CLIENT));
-}
-
-/*
- * Interface between xdr serializer and tcp connection.
- * Behaves like the system calls, read & write, but keeps some error state
- * around for the rpc level.
- */
-static int
-readtcp(ct, buf, len)
- register struct ct_data *ct;
- caddr_t buf;
- register int len;
-{
- fd_set *fds, readfds;
- struct timeval start, after, duration, delta, tmp, tv;
- int r, save_errno;
-
- if (len == 0)
- return (0);
-
- if (ct->ct_sock + 1 > FD_SETSIZE) {
- int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL)
- return (-1);
- memset(fds, 0, bytes);
- } else {
- fds = &readfds;
- FD_ZERO(fds);
- }
-
- gettimeofday(&start, NULL);
- delta = ct->ct_wait;
- while (TRUE) {
- /* XXX we know the other bits are still clear */
- FD_SET(ct->ct_sock, fds);
- tv = delta; /* in case select writes back */
- r = _select(ct->ct_sock+1, fds, NULL, NULL, &tv);
- save_errno = errno;
-
- gettimeofday(&after, NULL);
- timersub(&start, &after, &duration);
- timersub(&ct->ct_wait, &duration, &tmp);
- delta = tmp;
- if (delta.tv_sec < 0 || !timerisset(&delta))
- r = 0;
-
- switch (r) {
- case 0:
- if (fds != &readfds)
- free(fds);
- ct->ct_error.re_status = RPC_TIMEDOUT;
- return (-1);
-
- case -1:
- if (errno == EINTR)
- continue;
- if (fds != &readfds)
- free(fds);
- ct->ct_error.re_status = RPC_CANTRECV;
- ct->ct_error.re_errno = save_errno;
- return (-1);
- }
- break;
- }
- switch (len = _read(ct->ct_sock, buf, len)) {
-
- case 0:
- /* premature eof */
- ct->ct_error.re_errno = ECONNRESET;
- ct->ct_error.re_status = RPC_CANTRECV;
- len = -1; /* it's really an error */
- break;
-
- case -1:
- ct->ct_error.re_errno = errno;
- ct->ct_error.re_status = RPC_CANTRECV;
- break;
- }
- return (len);
-}
-
-static int
-writetcp(ct, buf, len)
- struct ct_data *ct;
- caddr_t buf;
- int len;
-{
- register int i, cnt;
-
- for (cnt = len; cnt > 0; cnt -= i, buf += i) {
- if ((i = _write(ct->ct_sock, buf, cnt)) == -1) {
- ct->ct_error.re_errno = errno;
- ct->ct_error.re_status = RPC_CANTSEND;
- return (-1);
- }
- }
- return (len);
-}
diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c
deleted file mode 100644
index bc103ed09503..000000000000
--- a/lib/libc/rpc/clnt_udp.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * clnt_udp.c, Implements a UDP/IP based, client side RPC.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#include <errno.h>
-#include <rpc/pmap_clnt.h>
-#include "un-namespace.h"
-
-/*
- * UDP bases client side rpc operations
- */
-static enum clnt_stat clntudp_call();
-static void clntudp_abort();
-static void clntudp_geterr();
-static bool_t clntudp_freeres();
-static bool_t clntudp_control();
-static void clntudp_destroy();
-
-static struct clnt_ops udp_ops = {
- clntudp_call,
- clntudp_abort,
- clntudp_geterr,
- clntudp_freeres,
- clntudp_destroy,
- clntudp_control
-};
-
-/*
- * Private data kept per client handle
- */
-struct cu_data {
- int cu_sock;
- bool_t cu_closeit;
- struct sockaddr_in cu_raddr;
- int cu_rlen;
- struct timeval cu_wait;
- struct timeval cu_total;
- struct rpc_err cu_error;
- XDR cu_outxdrs;
- u_int cu_xdrpos;
- u_int cu_sendsz;
- char *cu_outbuf;
- u_int cu_recvsz;
- char cu_inbuf[1];
-};
-
-/*
- * Create a UDP based client handle.
- * If *sockp<0, *sockp is set to a newly created UPD socket.
- * If raddr->sin_port is 0 a binder on the remote machine
- * is consulted for the correct port number.
- * NB: It is the clients responsibility to close *sockp.
- * NB: The rpch->cl_auth is initialized to null authentication.
- * Caller may wish to set this something more useful.
- *
- * wait is the amount of time used between retransmitting a call if
- * no response has been heard; retransmition occurs until the actual
- * rpc call times out.
- *
- * sendsz and recvsz are the maximum allowable packet sizes that can be
- * sent and received.
- */
-CLIENT *
-clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
- struct sockaddr_in *raddr;
- u_long program;
- u_long version;
- struct timeval wait;
- register int *sockp;
- u_int sendsz;
- u_int recvsz;
-{
- CLIENT *cl;
- register struct cu_data *cu = NULL;
- struct timeval now;
- struct rpc_msg call_msg;
- static u_int32_t disrupt;
-
- if (disrupt == 0)
- disrupt = (u_int32_t)(long)raddr;
-
- cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
- if (cl == NULL) {
- (void) fprintf(stderr, "clntudp_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
- sendsz = ((sendsz + 3) / 4) * 4;
- recvsz = ((recvsz + 3) / 4) * 4;
- cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
- if (cu == NULL) {
- (void) fprintf(stderr, "clntudp_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
- cu->cu_outbuf = &cu->cu_inbuf[recvsz];
-
- (void)gettimeofday(&now, (struct timezone *)0);
- if (raddr->sin_port == 0) {
- u_short port;
- if ((port =
- pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
- goto fooy;
- }
- raddr->sin_port = htons(port);
- }
- cl->cl_ops = &udp_ops;
- cl->cl_private = (caddr_t)cu;
- cu->cu_raddr = *raddr;
- cu->cu_rlen = sizeof (cu->cu_raddr);
- cu->cu_wait = wait;
- cu->cu_total.tv_sec = -1;
- cu->cu_total.tv_usec = -1;
- cu->cu_sendsz = sendsz;
- cu->cu_recvsz = recvsz;
- call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
- call_msg.rm_direction = CALL;
- call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- 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)) {
- goto fooy;
- }
- cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
- if (*sockp < 0) {
- int dontblock = 1;
-
- *sockp = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (*sockp < 0) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
- /* attempt to bind to priv port */
- (void)bindresvport(*sockp, (struct sockaddr_in *)0);
- /* the sockets rpc controls are non-blocking */
- (void)_ioctl(*sockp, FIONBIO, (char *) &dontblock);
- cu->cu_closeit = TRUE;
- } else {
- cu->cu_closeit = FALSE;
- }
- cu->cu_sock = *sockp;
- cl->cl_auth = authnone_create();
- return (cl);
-fooy:
- if (cu)
- mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
- if (cl)
- mem_free((caddr_t)cl, sizeof(CLIENT));
- return ((CLIENT *)NULL);
-}
-
-CLIENT *
-clntudp_create(raddr, program, version, wait, sockp)
- struct sockaddr_in *raddr;
- u_long program;
- u_long version;
- struct timeval wait;
- register int *sockp;
-{
-
- return(clntudp_bufcreate(raddr, program, version, wait, sockp,
- UDPMSGSIZE, UDPMSGSIZE));
-}
-
-static enum clnt_stat
-clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
- register CLIENT *cl; /* client handle */
- u_long 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 */
- struct timeval utimeout; /* seconds to wait before giving up */
-{
- register struct cu_data *cu = (struct cu_data *)cl->cl_private;
- register XDR *xdrs;
- register int outlen;
- register int inlen;
- int fromlen;
- fd_set *fds, readfds;
- struct sockaddr_in from;
- struct rpc_msg reply_msg;
- XDR reply_xdrs;
- struct timeval time_waited, start, after, tmp1, tmp2, tv;
- bool_t ok;
- int nrefreshes = 2; /* number of times to refresh cred */
- struct timeval timeout;
-
- if (cu->cu_total.tv_usec == -1)
- timeout = utimeout; /* use supplied timeout */
- else
- timeout = cu->cu_total; /* use default timeout */
-
- if (cu->cu_sock + 1 > FD_SETSIZE) {
- int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL)
- return (cu->cu_error.re_status = RPC_CANTSEND);
- memset(fds, 0, bytes);
- } else {
- fds = &readfds;
- FD_ZERO(fds);
- }
-
- timerclear(&time_waited);
-
-call_again:
- xdrs = &(cu->cu_outxdrs);
- xdrs->x_op = XDR_ENCODE;
- XDR_SETPOS(xdrs, cu->cu_xdrpos);
- /*
- * the transaction is the first thing in the out buffer
- */
- (*(u_short *)(cu->cu_outbuf))++;
- if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
- (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
- (! (*xargs)(xdrs, argsp))) {
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
- }
- outlen = (int)XDR_GETPOS(xdrs);
-
-send_again:
- if (_sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
- (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
- cu->cu_error.re_errno = errno;
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_CANTSEND);
- }
-
- /*
- * Hack to provide rpc-based message passing
- */
- if (!timerisset(&timeout)) {
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_TIMEDOUT);
- }
- /*
- * 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;
-
- gettimeofday(&start, NULL);
- for (;;) {
- /* XXX we know the other bits are still clear */
- FD_SET(cu->cu_sock, fds);
- tv = cu->cu_wait;
- switch (_select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {
-
- case 0:
- timeradd(&time_waited, &cu->cu_wait, &tmp1);
- time_waited = tmp1;
- if (timercmp(&time_waited, &timeout, <))
- goto send_again;
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_TIMEDOUT);
-
- case -1:
- if (errno == EINTR) {
- gettimeofday(&after, NULL);
- timersub(&after, &start, &tmp1);
- timeradd(&time_waited, &tmp1, &tmp2);
- time_waited = tmp2;
- if (timercmp(&time_waited, &timeout, <))
- continue;
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_TIMEDOUT);
- }
- cu->cu_error.re_errno = errno;
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_CANTRECV);
- }
-
- do {
- fromlen = sizeof(struct sockaddr);
- inlen = _recvfrom(cu->cu_sock, cu->cu_inbuf,
- (int) cu->cu_recvsz, 0,
- (struct sockaddr *)&from, &fromlen);
- } while (inlen < 0 && errno == EINTR);
- if (inlen < 0) {
- if (errno == EWOULDBLOCK)
- continue;
- cu->cu_error.re_errno = errno;
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status = RPC_CANTRECV);
- }
- if (inlen < sizeof(u_int32_t))
- continue;
- /* see if reply transaction id matches sent id */
- if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
- continue;
- /* we now assume we have the proper reply */
- break;
- }
-
- /*
- * now decode and validate the response
- */
- xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
- ok = xdr_replymsg(&reply_xdrs, &reply_msg);
- /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
- if (ok) {
- _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 */
- else {
- /* maybe our credentials need to be refreshed ... */
- if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
- nrefreshes--;
- goto call_again;
- }
- } /* end of unsuccessful completion */
- } /* end of valid reply message */
- else {
- /*
- * 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 = reply_xdrs.x_op;
- reply_xdrs.x_op = XDR_FREE;
- xdr_replymsg(&reply_xdrs, &reply_msg);
- reply_xdrs.x_op = op;
- cu->cu_error.re_status = RPC_CANTDECODERES;
- }
- if (fds != &readfds)
- free(fds);
- return (cu->cu_error.re_status);
-}
-
-static void
-clntudp_geterr(cl, errp)
- CLIENT *cl;
- struct rpc_err *errp;
-{
- register struct cu_data *cu = (struct cu_data *)cl->cl_private;
-
- *errp = cu->cu_error;
-}
-
-
-static bool_t
-clntudp_freeres(cl, xdr_res, res_ptr)
- CLIENT *cl;
- xdrproc_t xdr_res;
- caddr_t res_ptr;
-{
- register struct cu_data *cu = (struct cu_data *)cl->cl_private;
- register XDR *xdrs = &(cu->cu_outxdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_res)(xdrs, res_ptr));
-}
-
-static void
-clntudp_abort(/*h*/)
- /*CLIENT *h;*/
-{
-}
-
-
-static bool_t
-clntudp_control(cl, request, info)
- CLIENT *cl;
- int request;
- char *info;
-{
- register struct cu_data *cu = (struct cu_data *)cl->cl_private;
- register struct timeval *tv;
- int len;
-
- switch (request) {
- case CLSET_FD_CLOSE:
- cu->cu_closeit = TRUE;
- break;
- case CLSET_FD_NCLOSE:
- cu->cu_closeit = FALSE;
- break;
- case CLSET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- tv = (struct timeval *)info;
- cu->cu_total.tv_sec = tv->tv_sec;
- cu->cu_total.tv_usec = tv->tv_usec;
- break;
- case CLGET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- *(struct timeval *)info = cu->cu_total;
- break;
- case CLSET_RETRY_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- tv = (struct timeval *)info;
- cu->cu_wait.tv_sec = tv->tv_sec;
- cu->cu_wait.tv_usec = tv->tv_usec;
- break;
- case CLGET_RETRY_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- *(struct timeval *)info = cu->cu_wait;
- break;
- case CLGET_SERVER_ADDR:
- if (info == NULL)
- return(FALSE);
- *(struct sockaddr_in *)info = cu->cu_raddr;
- break;
- case CLGET_FD:
- if (info == NULL)
- return(FALSE);
- *(int *)info = cu->cu_sock;
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);
- break;
- case CLSET_XID:
- /* This will set the xid of the NEXT call */
- if (info == NULL)
- return(FALSE);
- *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1);
- /* decrement by 1 as clntudp_call() increments once */
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
- 4 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_VERS:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_PROG:
- /*
- * This RELIES on the information that, in the call body,
- * the program number field is the field from the
- * begining of the RPC header. MUST be changed if the
- * call_struct is changed
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
- 3 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_PROG:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_LOCAL_ADDR:
- len = sizeof(struct sockaddr);
- if (_getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0)
- return(FALSE);
- break;
- case CLGET_SVC_ADDR:
- case CLSET_SVC_ADDR:
- case CLSET_PUSH_TIMOD:
- case CLSET_POP_TIMOD:
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-static void
-clntudp_destroy(cl)
- CLIENT *cl;
-{
- register struct cu_data *cu = (struct cu_data *)cl->cl_private;
-
- if (cu->cu_closeit) {
- (void)_close(cu->cu_sock);
- }
- XDR_DESTROY(&(cu->cu_outxdrs));
- mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
- mem_free((caddr_t)cl, sizeof(CLIENT));
-}
diff --git a/lib/libc/rpc/clnt_unix.c b/lib/libc/rpc/clnt_unix.c
deleted file mode 100644
index d55859ca1fdb..000000000000
--- a/lib/libc/rpc/clnt_unix.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * clnt_unix.c, Implements a AF_UNIX based, client side RPC.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- *
- * AF_UNIX based RPC supports 'batched calls'.
- * A sequence of calls may be batched-up in a send buffer. The rpc call
- * return immediately to the client even though the call was not necessarily
- * sent. The batching occurs if the results' xdr routine is NULL (0) AND
- * the rpc timeout value is zero (see clnt.h, rpc).
- *
- * Clients should NOT casually batch calls that in fact return results; that is,
- * the server side should be aware that a call is batched and not produce any
- * return message. Batched calls that produce many result messages can
- * deadlock (netlock) the client and the server....
- *
- * Now go hang yourself.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netdb.h>
-#include <errno.h>
-#include <rpc/pmap_clnt.h>
-#include "un-namespace.h"
-
-#define MCALL_MSG_SIZE 24
-
-static int readunix();
-static int writeunix();
-
-static enum clnt_stat clntunix_call();
-static void clntunix_abort();
-static void clntunix_geterr();
-static bool_t clntunix_freeres();
-static bool_t clntunix_control();
-static void clntunix_destroy();
-
-static struct clnt_ops unix_ops = {
- clntunix_call,
- clntunix_abort,
- clntunix_geterr,
- clntunix_freeres,
- clntunix_destroy,
- clntunix_control
-};
-
-struct ct_data {
- int ct_sock;
- bool_t ct_closeit;
- struct timeval ct_wait;
- bool_t ct_waitset; /* wait set by clnt_control? */
- struct sockaddr_un ct_addr;
- struct rpc_err ct_error;
- char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
- u_int ct_mpos; /* pos after marshal */
- XDR ct_xdrs;
-};
-
-/*
- * Create a client handle for a unix/ip connection.
- * If *sockp<0, *sockp is set to a newly created TCP socket and it is
- * connected to raddr. If *sockp non-negative then
- * raddr is ignored. The rpc/unix package does buffering
- * similar to stdio, so the client must pick send and receive buffer sizes,];
- * 0 => use the default.
- * If raddr->sin_port is 0, then a binder on the remote machine is
- * consulted for the right port number.
- * NB: *sockp is copied into a private area.
- * NB: It is the clients responsibility to close *sockp.
- * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
- * something more useful.
- */
-CLIENT *
-clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
- struct sockaddr_un *raddr;
- u_long prog;
- u_long vers;
- register int *sockp;
- u_int sendsz;
- u_int recvsz;
-{
- CLIENT *h;
- register struct ct_data *ct = NULL;
- struct timeval now;
- struct rpc_msg call_msg;
- static u_int32_t disrupt;
- int len;
-
- if (disrupt == 0)
- disrupt = (u_int32_t)(long)raddr;
-
- h = (CLIENT *)mem_alloc(sizeof(*h));
- if (h == NULL) {
- (void)fprintf(stderr, "clntunix_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
- ct = (struct ct_data *)mem_alloc(sizeof(*ct));
- if (ct == NULL) {
- (void)fprintf(stderr, "clntunix_create: out of memory\n");
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- goto fooy;
- }
-
- /*
- * If no socket given, open one
- */
- if (*sockp < 0) {
- *sockp = _socket(AF_UNIX, SOCK_STREAM, 0);
- len = strlen(raddr->sun_path) + sizeof(raddr->sun_family) +
- sizeof(raddr->sun_len) + 1;
- raddr->sun_len = len;
- if ((*sockp < 0)
- || (_connect(*sockp, (struct sockaddr *)raddr, len) < 0)) {
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
- rpc_createerr.cf_error.re_errno = errno;
- if (*sockp != -1)
- (void)_close(*sockp);
- goto fooy;
- }
- ct->ct_closeit = TRUE;
- } else {
- ct->ct_closeit = FALSE;
- }
-
- /*
- * Set up private data struct
- */
- ct->ct_sock = *sockp;
- ct->ct_wait.tv_usec = 0;
- ct->ct_waitset = FALSE;
- ct->ct_addr = *raddr;
-
- /*
- * Initialize call message
- */
- (void)gettimeofday(&now, (struct timezone *)0);
- call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
- call_msg.rm_direction = CALL;
- call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- call_msg.rm_call.cb_prog = prog;
- call_msg.rm_call.cb_vers = vers;
-
- /*
- * pre-serialize the static part of the call msg and stash it away
- */
- xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
- XDR_ENCODE);
- if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
- if (ct->ct_closeit) {
- (void)_close(*sockp);
- }
- goto fooy;
- }
- ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
- XDR_DESTROY(&(ct->ct_xdrs));
-
- /*
- * Create a client handle which uses xdrrec for serialization
- * and authnone for authentication.
- */
- xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
- (caddr_t)ct, readunix, writeunix);
- h->cl_ops = &unix_ops;
- h->cl_private = (caddr_t) ct;
- h->cl_auth = authnone_create();
- return (h);
-
-fooy:
- /*
- * Something goofed, free stuff and barf
- */
- if (ct)
- mem_free((caddr_t)ct, sizeof(struct ct_data));
- if (h)
- mem_free((caddr_t)h, sizeof(CLIENT));
- return ((CLIENT *)NULL);
-}
-
-static enum clnt_stat
-clntunix_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
- register CLIENT *h;
- u_long proc;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
- xdrproc_t xdr_results;
- caddr_t results_ptr;
- struct timeval timeout;
-{
- register struct ct_data *ct = (struct ct_data *) h->cl_private;
- register XDR *xdrs = &(ct->ct_xdrs);
- struct rpc_msg reply_msg;
- u_long x_id;
- u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
- register bool_t shipnow;
- int refreshes = 2;
-
- if (!ct->ct_waitset) {
- ct->ct_wait = timeout;
- }
-
- shipnow =
- (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
- && timeout.tv_usec == 0) ? FALSE : TRUE;
-
-call_again:
- xdrs->x_op = XDR_ENCODE;
- ct->ct_error.re_status = RPC_SUCCESS;
- x_id = ntohl(--(*msg_x_id));
- if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
- (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
- (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
- (! (*xdr_args)(xdrs, args_ptr))) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- ct->ct_error.re_status = RPC_CANTENCODEARGS;
- (void)xdrrec_endofrecord(xdrs, TRUE);
- return (ct->ct_error.re_status);
- }
- if (! xdrrec_endofrecord(xdrs, shipnow))
- return (ct->ct_error.re_status = RPC_CANTSEND);
- if (! shipnow)
- return (RPC_SUCCESS);
- /*
- * Hack to provide rpc-based message passing
- */
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
- return(ct->ct_error.re_status = RPC_TIMEDOUT);
- }
-
-
- /*
- * Keep receiving until we get a valid transaction id
- */
- xdrs->x_op = XDR_DECODE;
- while (TRUE) {
- reply_msg.acpted_rply.ar_verf = _null_auth;
- reply_msg.acpted_rply.ar_results.where = NULL;
- reply_msg.acpted_rply.ar_results.proc = xdr_void;
- if (! xdrrec_skiprecord(xdrs))
- return (ct->ct_error.re_status);
- /* now decode and validate the response header */
- if (! xdr_replymsg(xdrs, &reply_msg)) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- continue;
- return (ct->ct_error.re_status);
- }
- if (reply_msg.rm_xid == x_id)
- break;
- }
-
- /*
- * process header
- */
- _seterr_reply(&reply_msg, &(ct->ct_error));
- if (ct->ct_error.re_status == RPC_SUCCESS) {
- if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
- ct->ct_error.re_status = RPC_AUTHERROR;
- ct->ct_error.re_why = AUTH_INVALIDRESP;
- } else if (! (*xdr_results)(xdrs, results_ptr)) {
- if (ct->ct_error.re_status == RPC_SUCCESS)
- ct->ct_error.re_status = RPC_CANTDECODERES;
- }
- /* free verifier ... */
- 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 */
- else {
- /* maybe our credentials need to be refreshed ... */
- if (refreshes-- && AUTH_REFRESH(h->cl_auth))
- goto call_again;
- } /* end of unsuccessful completion */
- return (ct->ct_error.re_status);
-}
-
-static void
-clntunix_geterr(h, errp)
- CLIENT *h;
- struct rpc_err *errp;
-{
- register struct ct_data *ct =
- (struct ct_data *) h->cl_private;
-
- *errp = ct->ct_error;
-}
-
-static bool_t
-clntunix_freeres(cl, xdr_res, res_ptr)
- CLIENT *cl;
- xdrproc_t xdr_res;
- caddr_t res_ptr;
-{
- register struct ct_data *ct = (struct ct_data *)cl->cl_private;
- register XDR *xdrs = &(ct->ct_xdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_res)(xdrs, res_ptr));
-}
-
-static void
-clntunix_abort()
-{
-}
-
-
-static bool_t
-clntunix_control(cl, request, info)
- CLIENT *cl;
- int request;
- char *info;
-{
- register struct ct_data *ct = (struct ct_data *)cl->cl_private;
- register struct timeval *tv;
- int len;
-
- switch (request) {
- case CLSET_FD_CLOSE:
- ct->ct_closeit = TRUE;
- break;
- case CLSET_FD_NCLOSE:
- ct->ct_closeit = FALSE;
- break;
- case CLSET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- tv = (struct timeval *)info;
- ct->ct_wait.tv_sec = tv->tv_sec;
- ct->ct_wait.tv_usec = tv->tv_usec;
- ct->ct_waitset = TRUE;
- break;
- case CLGET_TIMEOUT:
- if (info == NULL)
- return(FALSE);
- *(struct timeval *)info = ct->ct_wait;
- break;
- case CLGET_SERVER_ADDR:
- if (info == NULL)
- return(FALSE);
- *(struct sockaddr_un *)info = ct->ct_addr;
- break;
- case CLGET_FD:
- if (info == NULL)
- return(FALSE);
- *(int *)info = ct->ct_sock;
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
- break;
- case CLSET_XID:
- /* This will set the xid of the NEXT call */
- if (info == NULL)
- return(FALSE);
- *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
- /* decrement by 1 as clntunix_call() increments once */
- 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
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
- 4 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_VERS:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_PROG:
- /*
- * This RELIES on the information that, in the call body,
- * the program number field is the field from the
- * begining of the RPC header. MUST be changed if the
- * call_struct is changed
- */
- if (info == NULL)
- return(FALSE);
- *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
- 3 * BYTES_PER_XDR_UNIT));
- break;
- case CLSET_PROG:
- if (info == NULL)
- return(FALSE);
- *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
- = htonl(*(u_long *)info);
- break;
- case CLGET_LOCAL_ADDR:
- len = sizeof(struct sockaddr);
- if (_getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
- return(FALSE);
- break;
- case CLGET_RETRY_TIMEOUT:
- case CLSET_RETRY_TIMEOUT:
- case CLGET_SVC_ADDR:
- case CLSET_SVC_ADDR:
- case CLSET_PUSH_TIMOD:
- case CLSET_POP_TIMOD:
- default:
- return (FALSE);
- }
- return (TRUE);
-}
-
-
-static void
-clntunix_destroy(h)
- CLIENT *h;
-{
- register struct ct_data *ct =
- (struct ct_data *) h->cl_private;
-
- if (ct->ct_closeit) {
- (void)_close(ct->ct_sock);
- }
- XDR_DESTROY(&(ct->ct_xdrs));
- mem_free((caddr_t)ct, sizeof(struct ct_data));
- mem_free((caddr_t)h, sizeof(CLIENT));
-}
-
-/*
- * _read() and _write() are replaced with _recvmsg()/_sendmsg() so that
- * we can pass ancillary control data. In this case, the data constists
- * of credential information which the kernel will fill in for us.
- * XXX: This code is specific to FreeBSD and will not work on other
- * platforms without the requisite kernel modifications.
- */
-struct cmessage {
- struct cmsghdr cmsg;
- struct cmsgcred cmcred;
-};
-
-static int __msgread(sock, buf, cnt)
- int sock;
- void *buf;
- size_t cnt;
-{
- struct iovec iov[1];
- struct msghdr msg;
- struct cmessage cm;
-
- bzero((char *)&cm, sizeof(cm));
- iov[0].iov_base = buf;
- iov[0].iov_len = cnt;
-
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = (caddr_t)&cm;
- msg.msg_controllen = sizeof(struct cmessage);
- msg.msg_flags = 0;
-
- return(_recvmsg(sock, &msg, 0));
-}
-
-static int __msgwrite(sock, buf, cnt)
- int sock;
- void *buf;
- size_t cnt;
-{
- struct iovec iov[1];
- struct msghdr msg;
- struct cmessage cm;
-
- bzero((char *)&cm, sizeof(cm));
- iov[0].iov_base = buf;
- iov[0].iov_len = cnt;
-
- cm.cmsg.cmsg_type = SCM_CREDS;
- cm.cmsg.cmsg_level = SOL_SOCKET;
- cm.cmsg.cmsg_len = sizeof(struct cmessage);
-
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = (caddr_t)&cm;
- msg.msg_controllen = sizeof(struct cmessage);
- msg.msg_flags = 0;
-
- return(_sendmsg(sock, &msg, 0));
-}
-
-/*
- * Interface between xdr serializer and unix connection.
- * Behaves like the system calls, read & write, but keeps some error state
- * around for the rpc level.
- */
-static int
-readunix(ct, buf, len)
- register struct ct_data *ct;
- caddr_t buf;
- register int len;
-{
- fd_set *fds, readfds;
- struct timeval start, after, duration, delta, tmp, tv;
- int r, save_errno;
-
- if (len == 0)
- return (0);
-
- if (ct->ct_sock + 1 > FD_SETSIZE) {
- int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL)
- return (-1);
- memset(fds, 0, bytes);
- } else {
- fds = &readfds;
- FD_ZERO(fds);
- }
-
- gettimeofday(&start, NULL);
- delta = ct->ct_wait;
- while (TRUE) {
- /* XXX we know the other bits are still clear */
- FD_SET(ct->ct_sock, fds);
- tv = delta; /* in case select writes back */
- r = _select(ct->ct_sock+1, fds, NULL, NULL, &tv);
- save_errno = errno;
-
- gettimeofday(&after, NULL);
- timersub(&start, &after, &duration);
- timersub(&delta, &duration, &tmp);
- delta = tmp;
- if (delta.tv_sec < 0 || !timerisset(&delta))
- r = 0;
-
- switch (r) {
- case 0:
- if (fds != &readfds)
- free(fds);
- ct->ct_error.re_status = RPC_TIMEDOUT;
- return (-1);
-
- case -1:
- if (errno == EINTR)
- continue;
- if (fds != &readfds)
- free(fds);
- ct->ct_error.re_status = RPC_CANTRECV;
- ct->ct_error.re_errno = save_errno;
- return (-1);
- }
- break;
- }
- switch (len = __msgread(ct->ct_sock, buf, len)) {
-
- case 0:
- /* premature eof */
- ct->ct_error.re_errno = ECONNRESET;
- ct->ct_error.re_status = RPC_CANTRECV;
- len = -1; /* it's really an error */
- break;
-
- case -1:
- ct->ct_error.re_errno = errno;
- ct->ct_error.re_status = RPC_CANTRECV;
- break;
- }
- return (len);
-}
-
-static int
-writeunix(ct, buf, len)
- struct ct_data *ct;
- caddr_t buf;
- int len;
-{
- register int i, cnt;
-
- for (cnt = len; cnt > 0; cnt -= i, buf += i) {
- if ((i = __msgwrite(ct->ct_sock, buf, cnt)) == -1) {
- ct->ct_error.re_errno = errno;
- ct->ct_error.re_status = RPC_CANTSEND;
- return (-1);
- }
- }
- return (len);
-}
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
new file mode 100644
index 000000000000..bce8fbe31ae1
--- /dev/null
+++ b/lib/libc/rpc/clnt_vc.c
@@ -0,0 +1,839 @@
+/* $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
+static char sccsid[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer. The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent. The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message. Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+#define MCALL_MSG_SIZE 24
+
+static enum clnt_stat clnt_vc_call __P((CLIENT *, rpcproc_t, xdrproc_t, caddr_t,
+ xdrproc_t, caddr_t, struct timeval));
+static void clnt_vc_geterr __P((CLIENT *, struct rpc_err *));
+static bool_t clnt_vc_freeres __P((CLIENT *, xdrproc_t, caddr_t));
+static void clnt_vc_abort __P((CLIENT *));
+static bool_t clnt_vc_control __P((CLIENT *, u_int, char *));
+static void clnt_vc_destroy __P((CLIENT *));
+static struct clnt_ops *clnt_vc_ops __P((void));
+static bool_t time_not_ok __P((struct timeval *));
+static int read_vc __P((caddr_t, caddr_t, int));
+static int write_vc __P((caddr_t, caddr_t, int));
+static int __msgwrite(int, void *, size_t);
+static int __msgread(int, void *, size_t);
+
+struct ct_data {
+ int ct_fd; /* connection's fd */
+ bool_t ct_closeit; /* close it on destroy */
+ struct timeval ct_wait; /* wait interval in milliseconds */
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct netbuf ct_addr; /* remote addr */
+ struct rpc_err ct_error;
+ union {
+ char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int32_t ct_mcalli;
+ } ct_u;
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs; /* XDR stream */
+};
+
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+
+/*
+ * 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 (vc_fd_locks), protected
+ * by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
+ * similarly protected. Vc_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.
+ * 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 *vc_fd_locks;
+extern mutex_t clnt_fd_lock;
+static cond_t *vc_cv;
+#define release_fd_lock(fd, mask) { \
+ mutex_lock(&clnt_fd_lock); \
+ if (__isthreaded) \
+ vc_fd_locks[fd] = 0; \
+ mutex_unlock(&clnt_fd_lock); \
+ thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \
+ cond_signal(&vc_cv[fd]); \
+}
+
+static const char clnt_vc_errstr[] = "%s : %s";
+static const char clnt_vc_str[] = "clnt_vc_create";
+static const char clnt_read_vc_str[] = "read_vc";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * Create a client handle for a connection.
+ * Default options are set, which the user can change using clnt_control()'s.
+ * The rpc/vc package does buffering similar to stdio, so the client
+ * must pick send and receive buffer sizes, 0 => use the default.
+ * NB: fd is copied into a private area.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to
+ * set this something more useful.
+ *
+ * fd should be an open socket
+ */
+CLIENT *
+clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
+ int fd; /* open file descriptor */
+ const struct netbuf *raddr; /* servers address */
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ u_int sendsz; /* buffer recv size */
+ u_int recvsz; /* buffer send size */
+{
+ CLIENT *cl; /* client handle */
+ struct ct_data *ct = NULL; /* client handle */
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+ sigset_t mask;
+ sigset_t newmask;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ struct __rpc_sockinfo si;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ cl = (CLIENT *)mem_alloc(sizeof (*cl));
+ ct = (struct ct_data *)mem_alloc(sizeof (*ct));
+ if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) {
+ (void) syslog(LOG_ERR, clnt_vc_errstr,
+ clnt_vc_str, __no_mem_str);
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto err;
+ }
+ ct->ct_addr.buf = NULL;
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ if (vc_fd_locks == (int *) NULL) {
+ int cv_allocsz, fd_allocsz;
+ int dtbsize = __rpc_dtbsize();
+
+ fd_allocsz = dtbsize * sizeof (int);
+ vc_fd_locks = (int *) mem_alloc(fd_allocsz);
+ if (vc_fd_locks == (int *) NULL) {
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ } else
+ memset(vc_fd_locks, '\0', fd_allocsz);
+
+ assert(vc_cv == (cond_t *) NULL);
+ cv_allocsz = dtbsize * sizeof (cond_t);
+ vc_cv = (cond_t *) mem_alloc(cv_allocsz);
+ if (vc_cv == (cond_t *) NULL) {
+ mem_free(vc_fd_locks, fd_allocsz);
+ vc_fd_locks = (int *) NULL;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ } else {
+ int i;
+
+ for (i = 0; i < dtbsize; i++)
+ cond_init(&vc_cv[i], 0, (void *) 0);
+ }
+ } else
+ assert(vc_cv != (cond_t *) NULL);
+
+ /*
+ * XXX - fvdl connecting while holding a mutex?
+ */
+ slen = sizeof ss;
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ if (errno != ENOTCONN) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ mutex_unlock(&clnt_fd_lock);
+ goto err;
+ }
+ if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ mutex_unlock(&clnt_fd_lock);
+ goto err;
+ }
+ }
+ mutex_unlock(&clnt_fd_lock);
+ if (!__rpc_fd2sockinfo(fd, &si))
+ goto err;
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+
+ ct->ct_closeit = FALSE;
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_fd = fd;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr.buf = malloc(raddr->maxlen);
+ if (ct->ct_addr.buf == NULL)
+ goto err;
+ memcpy(ct->ct_addr.buf, &raddr->buf, raddr->len);
+ ct->ct_addr.len = raddr->maxlen;
+ ct->ct_addr.maxlen = raddr->maxlen;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, NULL);
+ call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = (u_int32_t)prog;
+ call_msg.rm_call.cb_vers = (u_int32_t)vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)_close(fd);
+ }
+ goto err;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ cl->cl_ops = clnt_vc_ops();
+ cl->cl_private = ct;
+ cl->cl_auth = authnone_create();
+ 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);
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ cl->cl_private, read_vc, write_vc);
+ return (cl);
+
+err:
+ if (cl) {
+ if (ct) {
+ if (ct->ct_addr.len)
+ mem_free(ct->ct_addr.buf, ct->ct_addr.len);
+ mem_free((caddr_t)ct, sizeof (struct ct_data));
+ }
+ if (cl)
+ mem_free((caddr_t)cl, sizeof (CLIENT));
+ }
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ CLIENT *cl;
+ rpcproc_t proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ struct ct_data *ct = (struct ct_data *) cl->cl_private;
+ XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_int32_t x_id;
+ u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */
+ bool_t shipnow;
+ int refreshes = 2;
+ sigset_t mask, newmask;
+ int rpc_lock_value;
+
+ assert(cl != NULL);
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+ if (!ct->ct_waitset) {
+ /* If time is not within limits, we ignore it. */
+ if (time_not_ok(&timeout) == FALSE)
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == NULL && timeout.tv_sec == 0
+ && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+ xdrs->x_op = XDR_ENCODE;
+ ct->ct_error.re_status = RPC_SUCCESS;
+ x_id = ntohl(--(*msg_x_id));
+
+ if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xdr_args)(xdrs, args_ptr))) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ }
+ if (! shipnow) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (RPC_SUCCESS);
+ }
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ release_fd_lock(ct->ct_fd, mask);
+ return(ct->ct_error.re_status = RPC_TIMEDOUT);
+ }
+
+
+ /*
+ * Keep receiving until we get a valid transaction id
+ */
+ xdrs->x_op = XDR_DECODE;
+ while (TRUE) {
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+ if (! xdrrec_skiprecord(xdrs)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ /* now decode and validate the response header */
+ if (! xdr_replymsg(xdrs, &reply_msg)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ continue;
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ if (reply_msg.rm_xid == x_id)
+ break;
+ }
+
+ /*
+ * process header
+ */
+ _seterr_reply(&reply_msg, &(ct->ct_error));
+ if (ct->ct_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(cl->cl_auth,
+ &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! (*xdr_results)(xdrs, results_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTDECODERES;
+ }
+ /* free verifier ... */
+ 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 */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(cl->cl_auth, &reply_msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+}
+
+static void
+clnt_vc_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ struct ct_data *ct;
+
+ assert(cl != NULL);
+ assert(errp != NULL);
+
+ ct = (struct ct_data *) cl->cl_private;
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clnt_vc_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ struct ct_data *ct;
+ XDR *xdrs;
+ bool_t dummy;
+ sigset_t mask;
+ sigset_t newmask;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *)cl->cl_private;
+ xdrs = &(ct->ct_xdrs);
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_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(&vc_cv[ct->ct_fd]);
+
+ return dummy;
+}
+
+/*ARGSUSED*/
+static void
+clnt_vc_abort(cl)
+ CLIENT *cl;
+{
+}
+
+static bool_t
+clnt_vc_control(cl, request, info)
+ CLIENT *cl;
+ u_int request;
+ char *info;
+{
+ struct ct_data *ct;
+ void *infop = info;
+ sigset_t mask;
+ sigset_t newmask;
+ int rpc_lock_value;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *)cl->cl_private;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+ default:
+ break;
+ }
+
+ /* for other requests which use info */
+ if (info == NULL) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ switch (request) {
+ case CLSET_TIMEOUT:
+ if (time_not_ok((struct timeval *)(void *)info)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ ct->ct_wait = *(struct timeval *)infop;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)infop = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ (void) memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len);
+ break;
+ case CLGET_FD:
+ *(int *)(void *)info = ct->ct_fd;
+ break;
+ case CLGET_SVC_ADDR:
+ /* The caller should not free this memory area */
+ *(struct netbuf *)(void *)info = ct->ct_addr;
+ break;
+ case CLSET_SVC_ADDR: /* set to new address */
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ 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 *)(void *)info =
+ ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ *(u_int32_t *)(void *)&ct->ct_u.ct_mcalli =
+ htonl(*((u_int32_t *)(void *)info) + 1);
+ /* increment by 1 as clnt_vc_call() decrements 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 *)(void *)info =
+ ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_VERS:
+ *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 4 * BYTES_PER_XDR_UNIT) =
+ htonl(*(u_int32_t *)(void *)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 *)(void *)info =
+ ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_PROG:
+ *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 3 * BYTES_PER_XDR_UNIT) =
+ htonl(*(u_int32_t *)(void *)info);
+ break;
+
+ default:
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+}
+
+
+static void
+clnt_vc_destroy(cl)
+ CLIENT *cl;
+{
+ struct ct_data *ct = (struct ct_data *) cl->cl_private;
+ int ct_fd = ct->ct_fd;
+ sigset_t mask;
+ sigset_t newmask;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *) cl->cl_private;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct_fd])
+ cond_wait(&vc_cv[ct_fd], &clnt_fd_lock);
+ if (ct->ct_closeit && ct->ct_fd != -1) {
+ (void)_close(ct->ct_fd);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ if (ct->ct_addr.buf)
+ free(ct->ct_addr.buf);
+ mem_free(ct, sizeof(struct ct_data));
+ mem_free(cl, sizeof(CLIENT));
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ cond_signal(&vc_cv[ct_fd]);
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+read_vc(ctp, buf, len)
+ caddr_t ctp;
+ caddr_t buf;
+ int len;
+{
+ struct sockaddr sa;
+ socklen_t sal;
+ struct ct_data *ct = (struct ct_data *)(void *)ctp;
+ struct pollfd fd;
+ int milliseconds = (int)((ct->ct_wait.tv_sec * 1000) +
+ (ct->ct_wait.tv_usec / 1000));
+
+ if (len == 0)
+ return (0);
+ fd.fd = ct->ct_fd;
+ fd.events = POLLIN;
+ for (;;) {
+ switch (_poll(&fd, 1, milliseconds)) {
+ case 0:
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = errno;
+ return (-1);
+ }
+ break;
+ }
+
+ sal = sizeof(sa);
+ if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+ (sa.sa_family == AF_LOCAL)) {
+ len = __msgread(ct->ct_fd, buf, (size_t)len);
+ } else {
+ len = _read(ct->ct_fd, buf, (size_t)len);
+ }
+
+ switch (len) {
+ case 0:
+ /* premature eof */
+ ct->ct_error.re_errno = ECONNRESET;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ len = -1; /* it's really an error */
+ break;
+
+ case -1:
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ break;
+ }
+ return (len);
+}
+
+static int
+write_vc(ctp, buf, len)
+ caddr_t ctp;
+ caddr_t buf;
+ int len;
+{
+ struct sockaddr sa;
+ socklen_t sal;
+ struct ct_data *ct = (struct ct_data *)(void *)ctp;
+ int i, cnt;
+
+ sal = sizeof(sa);
+ if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+ (sa.sa_family == AF_LOCAL)) {
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(ct->ct_fd, buf,
+ (size_t)cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ } else {
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = _write(ct->ct_fd, buf, (size_t)cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ }
+ return (len);
+}
+
+static struct clnt_ops *
+clnt_vc_ops()
+{
+ static struct clnt_ops ops;
+ extern mutex_t ops_lock;
+ sigset_t mask, newmask;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&ops_lock);
+ if (ops.cl_call == NULL) {
+ ops.cl_call = clnt_vc_call;
+ ops.cl_abort = clnt_vc_abort;
+ ops.cl_geterr = clnt_vc_geterr;
+ ops.cl_freeres = clnt_vc_freeres;
+ ops.cl_destroy = clnt_vc_destroy;
+ ops.cl_control = clnt_vc_control;
+ }
+ mutex_unlock(&ops_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ return (&ops);
+}
+
+/*
+ * Make sure that the time is not garbage. -1 value is disallowed.
+ * Note this is different from time_not_ok in clnt_dg.c
+ */
+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);
+}
+
+__msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(_recvmsg(sock, &msg, 0));
+}
+
+static int
+__msgwrite(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ cm.cmsg.cmsg_type = SCM_CREDS;
+ cm.cmsg.cmsg_level = SOL_SOCKET;
+ cm.cmsg.cmsg_len = sizeof(struct cmessage);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(_sendmsg(sock, &msg, 0));
+}
diff --git a/lib/libc/rpc/crypt_client.c b/lib/libc/rpc/crypt_client.c
index ab01971657e7..a62cad2227f2 100644
--- a/lib/libc/rpc/crypt_client.c
+++ b/lib/libc/rpc/crypt_client.c
@@ -28,15 +28,15 @@
* 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.
- *
- * $FreeBSD$
*/
+#include "namespace.h"
#include <sys/types.h>
#include <rpc/des_crypt.h>
#include <rpc/des.h>
#include <string.h>
#include <rpcsvc/crypt.h>
+#include "un-namespace.h"
#ifndef lint
static const char rcsid[] = "$FreeBSD$";
diff --git a/lib/libc/rpc/get_myaddress.c b/lib/libc/rpc/get_myaddress.c
deleted file mode 100644
index 70c3ac00fb99..000000000000
--- a/lib/libc/rpc/get_myaddress.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * get_myaddress.c
- *
- * Get client's IP address via ioctl. This avoids using the yellowpages.
- * Copyright (C) 1984, Sun Microsystems, Inc.
- */
-
-#include "namespace.h"
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <rpc/pmap_prot.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include "un-namespace.h"
-
-/*
- * don't use gethostbyname, which would invoke yellow pages
- *
- * Avoid loopback interfaces. We return information from a loopback
- * interface only if there are no other possible interfaces.
- */
-int
-get_myaddress(addr)
- struct sockaddr_in *addr;
-{
- int s;
- char buf[BUFSIZ];
- struct ifconf ifc;
- struct ifreq ifreq, *ifr, *end;
- int loopback = 0, gotit = 0;
-
- if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- return(-1);
- }
- ifc.ifc_len = sizeof (buf);
- ifc.ifc_buf = buf;
- if (_ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
- _close(s);
- return(-1);
- }
-again:
- ifr = ifc.ifc_req;
- end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
-
- while (ifr < end) {
- memcpy(&ifreq, ifr, sizeof(ifreq));
- if (_ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
- _close(s);
- return(-1);
- }
- if (((ifreq.ifr_flags & IFF_UP) &&
- ifr->ifr_addr.sa_family == AF_INET &&
- !(ifreq.ifr_flags & IFF_LOOPBACK)) ||
- (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK)
- && (ifr->ifr_addr.sa_family == AF_INET)
- && (ifreq.ifr_flags & IFF_UP))) {
- *addr = *((struct sockaddr_in *)&ifr->ifr_addr);
- addr->sin_port = htons(PMAPPORT);
- gotit = 1;
- break;
- }
- if (ifr->ifr_addr.sa_len)
- ifr = (struct ifreq *) ((caddr_t) ifr +
- ifr->ifr_addr.sa_len -
- sizeof(struct sockaddr));
- ifr++;
- }
- if (gotit == 0 && loopback == 0) {
- loopback = 1;
- goto again;
- }
- (void)_close(s);
- return (gotit ? 0 : -1);
-}
diff --git a/lib/libc/rpc/getnetconfig.3 b/lib/libc/rpc/getnetconfig.3
new file mode 100644
index 000000000000..fb1151eebd4c
--- /dev/null
+++ b/lib/libc/rpc/getnetconfig.3
@@ -0,0 +1,182 @@
+.\" @(#)getnetconfig.3n 1.28 93/06/02 SMI; from SVr4
+.\" $NetBSD: getnetconfig.3,v 1.1 2000/06/02 23:11:11 fvdl Exp $
+.\" $FreeBSD$
+.\" 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
+.Fd #include <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 .
+.Fn getnetconfig
+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.
+.Fn getnetconfig
+can be used to search the entire netconfig
+file.
+.Fn getnetconfig
+returns
+.Dv NULL
+at the end of the file.
+.Fa handlep
+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.
+.Fn setnetconfig
+must be called before the first call to
+.Fn getnetconfig
+and may be called at any other time.
+.Fn setnetconfig
+need not be called before a call to
+.Fn getnetconfigent .
+.Fn setnetconfig
+returns a unique handle to be used by
+.Fn getnetconfig .
+.Pp
+.Fn endnetconfig
+should be called when processing is complete to release resources for reuse.
+.Fa handlep
+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.
+.Fn endnetconfig
+may not be called before
+.Fn setnetconfig .
+.Pp
+.Fn getnetconfigent
+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
+.Fn freenetconfigent
+frees the netconfig structure pointed to by
+.Fa netconfigp
+(previously returned by
+.Fn getnetconfigent ) .
+.Pp
+.Fn nc_perror
+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
+.Fn nc_sperror
+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
+.Fn nc_perror
+and
+.Fn nc_sperror
+can also be used with the
+.Ev NETPATH
+access routines defined in
+.Xr getnetpath 3 .
+.Sh RETURN VALUES
+.Fn setnetconfig
+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
+.Fn getnetconfig
+returns a pointer to the current entry in the netconfig
+database, formatted as a
+.Ft "struct netconfig" .
+.Fn getnetconfig
+returns
+.Dv NULL
+at the end of the file, or upon failure.
+.Pp
+.Fn endnetconfig
+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
+.Fn nc_sperror
+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
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
new file mode 100644
index 000000000000..c7278b1cf91b
--- /dev/null
+++ b/lib/libc/rpc/getnetconfig.c
@@ -0,0 +1,674 @@
+/* $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+#ifndef lint
+static char sccsid[] = "@(#)getnetconfig.c 1.12 91/12/19 SMI";
+#endif
+*/
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+/*
+ * 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 */
+
+/*
+ * 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"
+};
+
+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 __P((void));
+static int parse_ncp __P((char *, struct netconfig *));
+static struct netconfig *dup_ncp __P((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 pthread_mutex_t nc_lock;
+ static thread_key_t nc_key = 0;
+ static thread_key_t rce_key = 0;
+ int *nc_addr = NULL;
+ static int nc_error = 0;
+
+ if ((nc_addr = (int *)thr_getspecific(nc_key)) != 0) {
+ mutex_lock(&nc_lock);
+ if (thr_keycreate(&rce_key, free) != 0) {
+ mutex_unlock(&nc_lock);
+ return nc_addr;
+ }
+ mutex_unlock(&nc_lock);
+ }
+ if (nc_addr == 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;
+ }
+ 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;
+ if (parse_ncp(stringp, list->ncp) == -1) {
+ free(stringp);
+ free(np);
+ free(list);
+ return (NULL);
+ }
+ else {
+ /*
+ * 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)
+ 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 */
+
+ if (netid == NULL || strlen(netid) == 0) {
+ return (NULL);
+ }
+
+ /*
+ * 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) {
+ return (NULL);
+ }
+
+ if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
+ fclose(file);
+ return (NULL);
+ }
+ do {
+ int 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) == (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 */
+ stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */
+ /* 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;
+ 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", s, nc_sperror());
+}
+
+/*
+ * Duplicates the matched netconfig buffer.
+ */
+static struct netconfig *
+dup_ncp(ncp)
+struct netconfig *ncp;
+{
+ struct netconfig *p;
+ char *tmp;
+ 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
+ * neccessary 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, NULL) + 1;
+ p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
+ tmp = strchr(tmp, NULL) + 1;
+ p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
+ tmp = strchr(tmp, NULL) + 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, NULL) + 1;
+ p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
+ }
+ return(p);
+}
diff --git a/lib/libc/rpc/getnetpath.3 b/lib/libc/rpc/getnetpath.3
new file mode 100644
index 000000000000..913a4cb1e8b2
--- /dev/null
+++ b/lib/libc/rpc/getnetpath.3
@@ -0,0 +1,154 @@
+.\" @(#)getnetpath.3n 1.26 93/05/07 SMI; from SVr4
+.\" $NetBSD: getnetpath.3,v 1.1 2000/06/02 23:11:11 fvdl Exp $
+.\" $FreeBSD$
+.\" 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
+.Fd #include <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 5 ) .
+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
+.Fn getnetpath
+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.
+.Fn getnetpath
+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 .
+.Fn setnetpath
+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
+.Fn getnetpath
+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
+.Fn endnetpath
+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
+.Fn setnetpath
+returns a handle that is used by
+.Fn getnetpath .
+In case of an error,
+.Fn setnetpath
+returns
+.Dv NULL .
+.Pp
+.Fn endnetpath
+returns 0 on success and \-1 on failure
+(for example, if
+.Fn setnetpath
+was not called previously).
+.Fn nc_perror
+or
+.Fn nc_sperror
+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 environ 5 ,
+.Xr netconfig 5
diff --git a/lib/libc/rpc/getnetpath.c b/lib/libc/rpc/getnetpath.c
new file mode 100644
index 000000000000..132a5102a83b
--- /dev/null
+++ b/lib/libc/rpc/getnetpath.c
@@ -0,0 +1,273 @@
+/* $NetBSD: getnetpath.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+#ifndef lint
+static char sccsid[] = "@(#)getnetpath.c 1.11 91/12/19 SMI";
+#endif
+*/
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.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 __P((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[-1] == '\\') {
+ /* if slash was also escaped, carry on, otherwise find next token */
+ if (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 */
+}
diff --git a/lib/libc/rpc/getpublickey.c b/lib/libc/rpc/getpublickey.c
index 49227b41b5f4..6c8fe5e21534 100644
--- a/lib/libc/rpc/getpublickey.c
+++ b/lib/libc/rpc/getpublickey.c
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
/*
* Public key lookup routines
*/
+#include "namespace.h"
#include <stdio.h>
#include <pwd.h>
#include <rpc/rpc.h>
@@ -49,6 +50,7 @@ static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
#include <rpcsvc/ypclnt.h>
#include <string.h>
#include <stdlib.h>
+#include "un-namespace.h"
#define PKFILE "/etc/publickey"
diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3
index 208e5d0ea104..6a02ca152c7f 100644
--- a/lib/libc/rpc/getrpcent.3
+++ b/lib/libc/rpc/getrpcent.3
@@ -1,4 +1,5 @@
.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
+.\" $NetBSD: getrpcent.3,v 1.6 1998/02/05 18:49:06 perry Exp $
.\" $FreeBSD$
.\"
.Dd December 14, 1987
@@ -11,6 +12,8 @@
.Nm endrpcent ,
.Nm setrpcent
.Nd get RPC entry
+.Sh LIBRARY
+.Lb libc
.Sh SYNOPSIS
.Fd #include <rpc/rpc.h>
.Ft struct rpcent *
@@ -24,19 +27,17 @@
.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
+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 .
+.Pa /etc/rpc :
.Bd -literal
-
-struct rpcent {
+struct rpcent {
char *r_name; /* name of server for this rpc program */
char **r_aliases; /* alias list */
long r_number; /* rpc program number */
@@ -44,29 +45,28 @@ struct rpcent {
.Ed
.Pp
The members of this structure are:
-.Bl -tag -width r_aliasesxxx
-.It Fa r_name
+.Bl -tag -width r_aliases -offset indent
+.It Va r_name
The name of the server for this rpc program.
-.It Fa r_aliases
+.It Va r_aliases
A zero terminated list of alternate names for the rpc program.
-.It Fa r_number
+.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.
-The
+reads the next line of the file, opening the file if necessary.
+.Pp
.Fn setrpcent
-function opens and rewinds the file. If the
+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
-.Fn getrpcent
-function family.
+.Dq getrpc
+calls).
.Pp
.Fn endrpcent
closes the file.
@@ -81,7 +81,7 @@ program number is found, or until end-of-file is encountered.
.Bl -tag -width /etc/rpc -compact
.It Pa /etc/rpc
.El
-.Sh "SEE ALSO"
+.Sh SEE ALSO
.Xr rpc 5 ,
.Xr rpcinfo 8 ,
.Xr ypserv 8
diff --git a/lib/libc/rpc/getrpcent.c b/lib/libc/rpc/getrpcent.c
index 4290235e686d..d200103c2281 100644
--- a/lib/libc/rpc/getrpcent.c
+++ b/lib/libc/rpc/getrpcent.c
@@ -1,3 +1,5 @@
+/* $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -28,8 +30,9 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/
+static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
static char *rcsid = "$FreeBSD$";
#endif
@@ -37,20 +40,29 @@ static char *rcsid = "$FreeBSD$";
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
+#include "namespace.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 <sys/types.h>
#include <string.h>
+
#include <rpc/rpc.h>
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
+#include "un-namespace.h"
/*
* Internet version.
*/
-struct rpcdata {
+static struct rpcdata {
FILE *rpcf;
int stayopen;
#define MAXALIASES 35
@@ -64,21 +76,21 @@ struct rpcdata {
#endif
} *rpcdata;
+static struct rpcent *interpret __P((char *val, size_t len));
+
#ifdef YP
static int __yp_nomap = 0;
extern int _yp_check(char **);
#endif /* YP */
-static struct rpcent *interpret();
-struct hostent *gethostent();
-char *inet_ntoa();
+#define RPCDB "/etc/rpc"
-static char RPCDB[] = "/etc/rpc";
+static struct rpcdata *_rpcdata __P((void));
static struct rpcdata *
_rpcdata()
{
- register struct rpcdata *d = rpcdata;
+ struct rpcdata *d = rpcdata;
if (d == 0) {
d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
@@ -89,14 +101,14 @@ _rpcdata()
struct rpcent *
getrpcbynumber(number)
- register int number;
+ int number;
{
- register struct rpcdata *d = _rpcdata();
- register struct rpcent *p;
#ifdef YP
int reason;
char adrstr[16];
#endif
+ struct rpcent *p;
+ struct rpcdata *d = _rpcdata();
if (d == 0)
return (0);
@@ -123,8 +135,9 @@ getrpcbynumber(number)
}
no_yp:
#endif /* YP */
+
setrpcent(0);
- while ((p = getrpcent())) {
+ while ((p = getrpcent()) != NULL) {
if (p->r_number == number)
break;
}
@@ -139,8 +152,10 @@ getrpcbyname(name)
struct rpcent *rpc = NULL;
char **rp;
+ assert(name != NULL);
+
setrpcent(0);
- while ((rpc = getrpcent())) {
+ while ((rpc = getrpcent()) != NULL) {
if (strcmp(rpc->r_name, name) == 0)
goto done;
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
@@ -157,7 +172,7 @@ void
setrpcent(f)
int f;
{
- register struct rpcdata *d = _rpcdata();
+ struct rpcdata *d = _rpcdata();
if (d == 0)
return;
@@ -181,7 +196,7 @@ setrpcent(f)
void
endrpcent()
{
- register struct rpcdata *d = _rpcdata();
+ struct rpcdata *d = _rpcdata();
if (d == 0)
return;
@@ -204,7 +219,7 @@ endrpcent()
struct rpcent *
getrpcent()
{
- register struct rpcdata *d = _rpcdata();
+ struct rpcdata *d = _rpcdata();
#ifdef YP
struct rpcent *hp;
int reason;
@@ -255,11 +270,13 @@ no_yp:
static struct rpcent *
interpret(val, len)
char *val;
- int len;
+ size_t len;
{
- register struct rpcdata *d = _rpcdata();
+ struct rpcdata *d = _rpcdata();
char *p;
- register char *cp, **q;
+ char *cp, **q;
+
+ assert(val != NULL);
if (d == 0)
return (0);
diff --git a/lib/libc/rpc/getrpcport.3 b/lib/libc/rpc/getrpcport.3
index b4fa8124d43e..3b6768532b6f 100644
--- a/lib/libc/rpc/getrpcport.3
+++ b/lib/libc/rpc/getrpcport.3
@@ -7,6 +7,8 @@
.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"
diff --git a/lib/libc/rpc/getrpcport.c b/lib/libc/rpc/getrpcport.c
index 24c6257fd886..193ef26e1afc 100644
--- a/lib/libc/rpc/getrpcport.c
+++ b/lib/libc/rpc/getrpcport.c
@@ -1,3 +1,5 @@
+/* $NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/
-/*static char *sccsid = "from: @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+static char *sccsid = "@(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -37,12 +40,18 @@ static char *rcsid = "$FreeBSD$";
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
+#include "namespace.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>
-#include <netdb.h>
-#include <sys/socket.h>
+#include "un-namespace.h"
int
getrpcport(host, prognum, versnum, proto)
@@ -52,12 +61,18 @@ getrpcport(host, 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_len = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = 0;
- memcpy((char *)&addr.sin_addr, hp->h_addr, hp->h_length);
- return (pmap_getport(&addr, prognum, versnum, proto));
+ if (hp->h_length > addr.sin_len)
+ hp->h_length = addr.sin_len;
+ 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));
}
diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c
index c6c3e78f1558..8adb29de1861 100644
--- a/lib/libc/rpc/key_call.c
+++ b/lib/libc/rpc/key_call.c
@@ -43,6 +43,7 @@
* gendeskey(deskey) - generate a secure des key
*/
+#include "reentrant.h"
#include "namespace.h"
#include <stdio.h>
#include <stdlib.h>
@@ -53,6 +54,7 @@
#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>
@@ -232,7 +234,7 @@ key_gendes(key)
int
key_setnet(arg)
-struct netstarg *arg;
+struct key_netstarg *arg;
{
keystatus status;
@@ -276,7 +278,6 @@ struct key_call_private {
};
static struct key_call_private *key_call_private_main = NULL;
-#ifdef foo
static void
key_call_destroy(void *vp)
{
@@ -288,7 +289,6 @@ key_call_destroy(void *vp)
free(kcp);
}
}
-#endif
/*
* Keep the handle cached. This call may be made quite often.
@@ -297,21 +297,40 @@ 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 main_thread;
int fd;
- struct sockaddr_un name;
- int namelen = sizeof(struct sockaddr_un);
+ static 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 ((main_thread = thr_main())) {
+ kcp = key_call_private_main;
+ } else {
+ if (key_call_key == 0) {
+ mutex_lock(&tsd_lock);
+ if (key_call_key == 0)
+ 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);
}
- key_call_private_main = kcp;
+ if (main_thread)
+ key_call_private_main = kcp;
+ else
+ thr_setspecific(key_call_key, (void *) kcp);
kcp->client = NULL;
}
@@ -322,16 +341,6 @@ int vers;
}
if (kcp->client != NULL) {
- /* if other side closed socket, build handle again */
- clnt_control(kcp->client, CLGET_FD, (char *)&fd);
- if (_getpeername(fd,(struct sockaddr *)&name,&namelen) == -1) {
- auth_destroy(kcp->client->cl_auth);
- 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();
@@ -348,15 +357,51 @@ int vers;
clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
return (kcp->client);
}
-
- if ((kcp->client == (CLIENT *) NULL))
- /* Use the AF_UNIX transport */
- kcp->client = clnt_create("/var/run/keyservsock", KEY_PROG,
- vers, "unix");
+ if (!(localhandle = setnetconfig())) {
+ return ((CLIENT *) NULL);
+ }
+ tpconf = NULL;
+#if defined(i386)
+#if defined(__FreeBSD__)
+ if (uname(&u) == -1)
+#else
+ if (_nuname(&u) == -1)
+#endif
+#elif defined(sparc)
+ if (_uname(&u) == -1)
+#else
+#error Unknown architecture!
+#endif
+ {
+ endnetconfig(localhandle);
+ return ((CLIENT *) NULL);
+ }
+
+ while (nconf = getnetconfig(localhandle)) {
+ 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);
diff --git a/lib/libc/rpc/key_prot_xdr.c b/lib/libc/rpc/key_prot_xdr.c
index 8cd6b6b0678e..298a451d2f77 100644
--- a/lib/libc/rpc/key_prot_xdr.c
+++ b/lib/libc/rpc/key_prot_xdr.c
@@ -3,7 +3,9 @@
* It was generated using rpcgen.
*/
+#include "namespace.h"
#include <rpc/key_prot.h>
+#include "un-namespace.h"
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -32,8 +34,8 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
-#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI"
-
+/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */
+/* $FreeBSD$ */
/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
/*
diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c
new file mode 100644
index 000000000000..5abf831fd750
--- /dev/null
+++ b/lib/libc/rpc/mt_misc.c
@@ -0,0 +1,125 @@
+/* $NetBSD: mt_misc.c,v 1.1 2000/06/02 23:11:11 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/* #pragma ident "@(#)mt_misc.c 1.24 93/04/29 SMI" */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+/* protects the services list (svc.c) */
+pthread_rwlock_t svc_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects svc_fdset and the xports[] array */
+pthread_rwlock_t svc_fd_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects the RPCBIND address cache */
+pthread_rwlock_t rpcbaddr_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects authdes cache (svcauth_des.c) */
+pthread_mutex_t authdes_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes authdes ops initializations */
+pthread_mutex_t authdes_ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects des stats list */
+pthread_mutex_t svcauthdesstats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#ifdef KERBEROS
+/* auth_kerb.c serialization */
+pthread_mutex_t authkerb_lock = PTHREAD_MUTEX_INITIALIZER;
+/* protects kerb stats list */
+pthread_mutex_t svcauthkerbstats_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif /* KERBEROS */
+
+/* auth_none.c serialization */
+pthread_mutex_t authnone_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects the Auths list (svc_auth.c) */
+pthread_mutex_t authsvc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects client-side fd lock array */
+pthread_mutex_t clnt_fd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* clnt_raw.c serialization */
+pthread_mutex_t clntraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* domainname and domain_fd (getdname.c) and default_domain (rpcdname.c) */
+pthread_mutex_t dname_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* dupreq variables (svc_dg.c) */
+pthread_mutex_t dupreq_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects first_time and hostname (key_call.c) */
+pthread_mutex_t keyserv_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes rpc_trace() (rpc_trace.c) */
+pthread_mutex_t libnsl_trace_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* loopnconf (rpcb_clnt.c) */
+pthread_mutex_t loopnconf_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes ops initializations */
+pthread_mutex_t ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects ``port'' static in bindresvport() */
+pthread_mutex_t portnum_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects proglst list (svc_simple.c) */
+pthread_mutex_t proglst_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes clnt_com_create() (rpc_soc.c) */
+pthread_mutex_t rpcsoc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* svc_raw.c serialization */
+pthread_mutex_t svcraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects TSD key creation */
+pthread_mutex_t tsd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects netconfig list */
+pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* xprtlist (svc_generic.c) */
+pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes calls to public key routines */
+pthread_mutex_t serialize_pkey = PTHREAD_MUTEX_INITIALIZER;
+
+#undef rpc_createerr
+
+struct rpc_createerr rpc_createerr;
+
+struct rpc_createerr *
+__rpc_createerr()
+{
+ static thread_key_t rce_key = 0;
+ struct rpc_createerr *rce_addr = 0;
+
+ if (thr_main())
+ return (&rpc_createerr);
+ if ((rce_addr =
+ (struct rpc_createerr *)thr_getspecific(rce_key)) != 0) {
+ mutex_lock(&tsd_lock);
+ if (thr_keycreate(&rce_key, free) != 0) {
+ mutex_unlock(&tsd_lock);
+ return (&rpc_createerr);
+ }
+ mutex_unlock(&tsd_lock);
+ }
+ if (!rce_addr) {
+ rce_addr = (struct rpc_createerr *)
+ malloc(sizeof (struct rpc_createerr));
+ if (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);
+ }
+ return (rce_addr);
+}
diff --git a/lib/libc/rpc/netconfig.5 b/lib/libc/rpc/netconfig.5
new file mode 100644
index 000000000000..25738bcc2efe
--- /dev/null
+++ b/lib/libc/rpc/netconfig.5
@@ -0,0 +1,126 @@
+.\" $NetBSD: netconfig.5,v 1.2 2000/11/08 13:18:28 lukem Exp $
+.\" $NetBSD: netconfig.5,v 1.2 2000/11/08 13:18:28 lukem Exp $
+.\" $FreeBSD$
+.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
diff --git a/lib/libc/rpc/netname.c b/lib/libc/rpc/netname.c
index cec14df72ab5..f598f78d3ee0 100644
--- a/lib/libc/rpc/netname.c
+++ b/lib/libc/rpc/netname.c
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
* the sun NIS domain architecture.
*/
+#include "namespace.h"
#include <sys/param.h>
#include <rpc/rpc.h>
#include <rpc/rpc_com.h>
@@ -54,6 +55,7 @@ static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "un-namespace.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
@@ -101,8 +103,8 @@ getnetname(name)
int
user2netname(netname, uid, domain)
char netname[MAXNETNAMELEN + 1];
- uid_t uid;
- char *domain;
+ const uid_t uid;
+ const char *domain;
{
char *dfltdom;
@@ -126,8 +128,8 @@ user2netname(netname, uid, domain)
int
host2netname(netname, host, domain)
char netname[MAXNETNAMELEN + 1];
- char *host;
- char *domain;
+ const char *host;
+ const char *domain;
{
char *dfltdom;
char hostname[MAXHOSTNAMELEN+1];
diff --git a/lib/libc/rpc/netnamer.c b/lib/libc/rpc/netnamer.c
index 2fa0a3c1bd57..36fa3dcd629c 100644
--- a/lib/libc/rpc/netnamer.c
+++ b/lib/libc/rpc/netnamer.c
@@ -38,6 +38,7 @@ static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
* will work with any unix system that has adopted the sun NIS domain
* architecture.
*/
+#include "namespace.h"
#include <sys/param.h>
#include <rpc/rpc.h>
#include <rpc/rpc_com.h>
@@ -52,6 +53,7 @@ static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include "un-namespace.h"
static char *OPSYS = "unix";
static char *NETID = "netid.byname";
diff --git a/lib/libc/rpc/pmap_clnt.c b/lib/libc/rpc/pmap_clnt.c
index 41bb78d582db..676444e1e5d4 100644
--- a/lib/libc/rpc/pmap_clnt.c
+++ b/lib/libc/rpc/pmap_clnt.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_clnt.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/
@@ -44,108 +47,74 @@ static char *rcsid = "$FreeBSD$";
#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 "un-namespace.h"
-static struct timeval timeout = { 5, 0 };
-static struct timeval tottimeout = { 60, 0 };
+#include <stdio.h>
+#include <stdlib.h>
-void clnt_perror();
+#include "rpc_com.h"
-#ifndef PORTMAPSOCK
-#define PORTMAPSOCK "/var/run/portmapsock"
-#endif
-
-/*
- * Set a mapping between program,version and port.
- * Calls the pmap service remotely to do the mapping.
- */
bool_t
-pmap_set(program, version, protocol, port)
- u_long program;
- u_long version;
- int protocol;
- u_short port;
+pmap_set(u_long program, u_long version, int protocol, int port)
{
- struct sockaddr_in myaddress;
- int socket = -1;
- register CLIENT *client;
- struct pmap parms;
bool_t rslt;
- struct stat st;
+ struct netbuf *na;
+ struct netconfig *nconf;
+ char buf[32];
- /*
- * Temporary hack for backwards compatibility. Eventually
- * this test will go away and we'll use only the "unix" transport.
- */
- if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
- client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
- else {
- if (get_myaddress(&myaddress) != 0)
- return (FALSE);
- myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
- timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
+ return (FALSE);
}
-
- if (client == (CLIENT *)NULL)
+ nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
+ if (nconf == NULL) {
return (FALSE);
- parms.pm_prog = program;
- parms.pm_vers = version;
- parms.pm_prot = protocol;
- parms.pm_port = port;
- if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
- tottimeout) != RPC_SUCCESS) {
- clnt_perror(client, "Cannot register service");
+ }
+ 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);
}
- CLNT_DESTROY(client);
- if (socket != -1)
- (void)_close(socket);
+ 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.
+ * Remove the mapping between program, version and port.
* Calls the pmap service remotely to do the un-mapping.
*/
bool_t
-pmap_unset(program, version)
- u_long program;
- u_long version;
+pmap_unset(u_long program, u_long version)
{
- struct sockaddr_in myaddress;
- int socket = -1;
- register CLIENT *client;
- struct pmap parms;
- bool_t rslt;
- struct stat st;
+ 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);
+ }
/*
- * Temporary hack for backwards compatibility. Eventually
- * this test will go away and we'll use only the "unix" transport.
+ * 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.
*/
- if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
- client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
- else {
- if (get_myaddress(&myaddress) != 0)
- return (FALSE);
- myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
- timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
- }
- if (client == (CLIENT *)NULL)
- return (FALSE);
- parms.pm_prog = program;
- parms.pm_vers = version;
- parms.pm_port = parms.pm_prot = 0;
- CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
- tottimeout);
- CLNT_DESTROY(client);
- if (socket != -1)
- (void)_close(socket);
- return (rslt);
+ return (tcp_rslt || udp_rslt);
}
diff --git a/lib/libc/rpc/pmap_getmaps.c b/lib/libc/rpc/pmap_getmaps.c
index b51ac696b0f3..4c8397f412d4 100644
--- a/lib/libc/rpc/pmap_getmaps.c
+++ b/lib/libc/rpc/pmap_getmaps.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/
@@ -42,16 +45,21 @@ static char *rcsid = "$FreeBSD$";
*/
#include "namespace.h"
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <rpc/pmap_clnt.h>
+#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <assert.h>
+#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
-#include <errno.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
#include "un-namespace.h"
#define NAMELEN 255
@@ -65,25 +73,27 @@ struct pmaplist *
pmap_getmaps(address)
struct sockaddr_in *address;
{
- struct pmaplist *head = (struct pmaplist *)NULL;
- int socket = -1;
+ struct pmaplist *head = NULL;
+ int sock = -1;
struct timeval minutetimeout;
- register CLIENT *client;
+ CLIENT *client;
+
+ assert(address != NULL);
minutetimeout.tv_sec = 60;
minutetimeout.tv_usec = 0;
address->sin_port = htons(PMAPPORT);
client = clnttcp_create(address, PMAPPROG,
- PMAPVERS, &socket, 50, 500);
- if (client != (CLIENT *)NULL) {
- if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
- &head, minutetimeout) != RPC_SUCCESS) {
+ 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);
}
- if (socket != -1)
- (void)_close(socket);
address->sin_port = 0;
return (head);
}
diff --git a/lib/libc/rpc/pmap_getport.c b/lib/libc/rpc/pmap_getport.c
index bef94fdf45eb..ff75c9ff1d62 100644
--- a/lib/libc/rpc/pmap_getport.c
+++ b/lib/libc/rpc/pmap_getport.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_getport.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";*/
@@ -41,16 +44,21 @@ static char *rcsid = "$FreeBSD$";
*/
#include "namespace.h"
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <rpc/pmap_clnt.h>
+#include <sys/types.h>
#include <sys/socket.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>
#include "un-namespace.h"
-static struct timeval timeout = { 5, 0 };
-static struct timeval tottimeout = { 60, 0 };
+static const struct timeval timeout = { 5, 0 };
+static const struct timeval tottimeout = { 60, 0 };
/*
* Find the mapped port for program,version.
@@ -65,20 +73,24 @@ pmap_getport(address, program, version, protocol)
u_int protocol;
{
u_short port = 0;
- int socket = -1;
- register CLIENT *client;
+ int sock = -1;
+ CLIENT *client;
struct pmap parms;
+ assert(address != NULL);
+
address->sin_port = htons(PMAPPORT);
client = clntudp_bufcreate(address, PMAPPROG,
- PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
- if (client != (CLIENT *)NULL) {
+ 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, PMAPPROC_GETPORT, xdr_pmap, &parms,
- xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
+ 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) {
@@ -86,8 +98,6 @@ pmap_getport(address, program, version, protocol)
}
CLNT_DESTROY(client);
}
- if (socket != -1)
- (void)_close(socket);
address->sin_port = 0;
return (port);
}
diff --git a/lib/libc/rpc/pmap_prot.c b/lib/libc/rpc/pmap_prot.c
index f42484299477..62b572562d57 100644
--- a/lib/libc/rpc/pmap_prot.c
+++ b/lib/libc/rpc/pmap_prot.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -40,9 +43,13 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "namespace.h"
+#include <assert.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
bool_t
@@ -51,6 +58,9 @@ xdr_pmap(xdrs, regs)
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))
diff --git a/lib/libc/rpc/pmap_prot2.c b/lib/libc/rpc/pmap_prot2.c
index 9c5230ddaeba..e30f977cb309 100644
--- a/lib/libc/rpc/pmap_prot2.c
+++ b/lib/libc/rpc/pmap_prot2.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -40,9 +43,13 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "namespace.h"
+#include <assert.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
/*
@@ -85,8 +92,8 @@ static char *rcsid = "$FreeBSD$";
*/
bool_t
xdr_pmaplist(xdrs, rp)
- register XDR *xdrs;
- register struct pmaplist **rp;
+ XDR *xdrs;
+ struct pmaplist **rp;
{
/*
* more_elements is pre-computed in case the direction is
@@ -94,10 +101,15 @@ xdr_pmaplist(xdrs, rp)
* xdr_bool when the direction is XDR_DECODE.
*/
bool_t more_elements;
- register int freeing = (xdrs->x_op == XDR_FREE);
- register struct pmaplist **next = NULL;
+ int freeing;
+ struct pmaplist **next = NULL; /* pacify gcc */
+
+ assert(xdrs != NULL);
+ assert(rp != NULL);
- while (TRUE) {
+ freeing = (xdrs->x_op == XDR_FREE);
+
+ for (;;) {
more_elements = (bool_t)(*rp != NULL);
if (! xdr_bool(xdrs, &more_elements))
return (FALSE);
@@ -109,10 +121,23 @@ xdr_pmaplist(xdrs, rp)
* before we free the current object ...
*/
if (freeing)
- next = &((*rp)->pml_next);
+ next = &((*rp)->pml_next);
if (! xdr_reference(xdrs, (caddr_t *)rp,
- (u_int)sizeof(struct pmaplist), xdr_pmap))
+ (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);
+}
diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c
index 298c95613e4e..51e6d3a0c3e0 100644
--- a/lib/libc/rpc/pmap_rmt.c
+++ b/lib/libc/rpc/pmap_rmt.c
@@ -1,3 +1,5 @@
+/* $NetBSD: pmap_rmt.c,v 1.29 2000/07/06 03:10:34 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/
@@ -42,24 +45,29 @@ static char *rcsid = "$FreeBSD$";
*/
#include "namespace.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>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
#include "un-namespace.h"
-#define MAX_BROADCAST_SIZE 1400
-
-static struct timeval timeout = { 3, 0 };
+static const struct timeval timeout = { 3, 0 };
/*
* pmapper remote-call-service interface.
@@ -69,7 +77,8 @@ static struct timeval timeout = { 3, 0 };
* 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)
+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;
@@ -77,15 +86,18 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt
struct timeval tout;
u_long *port_ptr;
{
- int socket = -1;
- register CLIENT *client;
+ 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, &socket);
- if (client != (CLIENT *)NULL) {
+ client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
+ if (client != NULL) {
a.prog = prog;
a.vers = vers;
a.proc = proc;
@@ -94,14 +106,13 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt
r.port_ptr = port_ptr;
r.results_ptr = resp;
r.xdr_results = xdrres;
- stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
- xdr_rmtcallres, &r, tout);
+ 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;
}
- if (socket != -1)
- (void)_close(socket);
addr->sin_port = 0;
return (stat);
}
@@ -113,11 +124,14 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt
*/
bool_t
xdr_rmtcall_args(xdrs, cap)
- register XDR *xdrs;
- register struct rmtcallargs *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))) {
@@ -144,275 +158,19 @@ xdr_rmtcall_args(xdrs, cap)
*/
bool_t
xdr_rmtcallres(xdrs, crp)
- register XDR *xdrs;
- register struct rmtcallres *crp;
+ XDR *xdrs;
+ struct rmtcallres *crp;
{
caddr_t port_ptr;
- port_ptr = (caddr_t)crp->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),
- xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
- crp->port_ptr = (u_long *)port_ptr;
+ (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);
}
-
-
-/*
- * The following is kludged-up support for simple rpc broadcasts.
- * Someday a large, complicated system will replace these trivial
- * routines which only support udp/ip .
- */
-
-static int
-getbroadcastnets(addrs, sock, buf)
- struct in_addr *addrs;
- int sock; /* any valid socket will do */
- char *buf; /* why allocxate more when we can use existing... */
-{
- struct ifconf ifc;
- struct ifreq ifreq, *ifr;
- struct sockaddr_in *sin;
- struct in_addr addr;
- char *cp, *cplim;
- int n, i = 0;
-
- ifc.ifc_len = UDPMSGSIZE;
- ifc.ifc_buf = buf;
- if (_ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
- perror("broadcast: ioctl (get interface configuration)");
- return (0);
- }
-#define max(a, b) (a > b ? a : b)
-#define size(p) max((p).sa_len, sizeof(p))
- cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
- for (cp = buf; cp < cplim;
- cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
- ifr = (struct ifreq *)cp;
- if (ifr->ifr_addr.sa_family != AF_INET)
- continue;
- memcpy(&ifreq, ifr, sizeof(ifreq));
- if (_ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
- perror("broadcast: ioctl (get interface flags)");
- continue;
- }
- if ((ifreq.ifr_flags & IFF_BROADCAST) &&
- (ifreq.ifr_flags & IFF_UP)) {
- sin = (struct sockaddr_in *)&ifr->ifr_addr;
-#ifdef SIOCGIFBRDADDR /* 4.3BSD */
- if (_ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
- addr =
- inet_makeaddr(inet_netof(sin->sin_addr),
- INADDR_ANY);
- } else {
- addr = ((struct sockaddr_in*)
- &ifreq.ifr_addr)->sin_addr;
- }
-#else /* 4.2 BSD */
- addr = inet_makeaddr(inet_netof(sin->sin_addr),
- INADDR_ANY);
-#endif
- for (n=i-1; n>=0; n--) {
- if (addr.s_addr == addrs[n].s_addr)
- break;
- }
- if (n<0) {
- addrs[i++] = addr;
- }
- }
- }
- return (i);
-}
-
-typedef bool_t (*resultproc_t)();
-
-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 */
- 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 */
-{
- enum clnt_stat stat;
- AUTH *unix_auth = authunix_create_default();
- XDR xdr_stream;
- register XDR *xdrs = &xdr_stream;
- int outlen, inlen, fromlen, nets;
- register int sock;
- int on = 1;
- fd_set *fds, readfds;
- register int i;
- bool_t done = FALSE;
- register u_long xid;
- u_long port;
- struct in_addr addrs[20];
- struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
- struct rmtcallargs a;
- struct rmtcallres r;
- struct rpc_msg msg;
- struct timeval t, tv;
- char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
- static u_int32_t disrupt;
-
- if (disrupt == 0)
- disrupt = (u_int32_t)(long)resultsp;
-
- /*
- * initialization: create a socket, a broadcast address, and
- * preserialize the arguments into a send buffer.
- */
- if ((sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- perror("Cannot create socket for broadcast rpc");
- stat = RPC_CANTSEND;
- goto done_broad;
- }
-#ifdef SO_BROADCAST
- if (_setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
- perror("Cannot set socket option SO_BROADCAST");
- stat = RPC_CANTSEND;
- goto done_broad;
- }
-#endif /* def SO_BROADCAST */
- if (sock + 1 > FD_SETSIZE) {
- int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL) {
- stat = RPC_CANTSEND;
- goto done_broad;
- }
- memset(fds, 0, bytes);
- } else {
- fds = &readfds;
- FD_ZERO(fds);
- }
-
- nets = getbroadcastnets(addrs, sock, inbuf);
- memset(&baddr, 0, sizeof (baddr));
- baddr.sin_len = sizeof(struct sockaddr_in);
- baddr.sin_family = AF_INET;
- baddr.sin_port = htons(PMAPPORT);
- baddr.sin_addr.s_addr = htonl(INADDR_ANY);
- (void)gettimeofday(&t, (struct timezone *)0);
- msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec;
- t.tv_usec = 0;
- msg.rm_direction = CALL;
- msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- msg.rm_call.cb_prog = PMAPPROG;
- msg.rm_call.cb_vers = PMAPVERS;
- msg.rm_call.cb_proc = PMAPPROC_CALLIT;
- msg.rm_call.cb_cred = unix_auth->ah_cred;
- msg.rm_call.cb_verf = unix_auth->ah_verf;
- a.prog = prog;
- a.vers = vers;
- a.proc = proc;
- a.xdr_args = xargs;
- a.args_ptr = argsp;
- r.port_ptr = &port;
- r.xdr_results = xresults;
- r.results_ptr = resultsp;
- xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
- if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
- stat = RPC_CANTENCODEARGS;
- goto done_broad;
- }
- outlen = (int)xdr_getpos(xdrs);
- xdr_destroy(xdrs);
- /*
- * Basic loop: broadcast a packet and wait a while for response(s).
- * The response timeout grows larger per iteration.
- *
- * XXX This will loop about 5 times the stop. If there are
- * lots of signals being received by the process it will quit
- * send them all in one quick burst, not paying attention to
- * the intended function of sending them slowly over half a
- * minute or so
- */
- for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
- for (i = 0; i < nets; i++) {
- baddr.sin_addr = addrs[i];
- if (_sendto(sock, outbuf, outlen, 0,
- (struct sockaddr *)&baddr,
- sizeof (struct sockaddr)) != outlen) {
- perror("Cannot send broadcast packet");
- stat = RPC_CANTSEND;
- goto done_broad;
- }
- }
- if (eachresult == NULL) {
- stat = RPC_SUCCESS;
- goto done_broad;
- }
- recv_again:
- msg.acpted_rply.ar_verf = _null_auth;
- msg.acpted_rply.ar_results.where = (caddr_t)&r;
- msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
- /* XXX we know the other bits are still clear */
- FD_SET(sock, fds);
- tv = t; /* for _select() that copies back */
- switch (_select(sock + 1, fds, NULL, NULL, &tv)) {
-
- case 0: /* timed out */
- stat = RPC_TIMEDOUT;
- continue;
-
- case -1: /* some kind of error */
- if (errno == EINTR)
- goto recv_again;
- perror("Broadcast select problem");
- stat = RPC_CANTRECV;
- goto done_broad;
-
- } /* end of select results switch */
- try_again:
- fromlen = sizeof(struct sockaddr);
- inlen = _recvfrom(sock, inbuf, UDPMSGSIZE, 0,
- (struct sockaddr *)&raddr, &fromlen);
- if (inlen < 0) {
- if (errno == EINTR)
- goto try_again;
- perror("Cannot receive reply to broadcast");
- stat = RPC_CANTRECV;
- goto done_broad;
- }
- if (inlen < sizeof(u_int32_t))
- goto recv_again;
- /*
- * see if reply transaction id matches sent id.
- * If so, decode the results.
- */
- xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
- if (xdr_replymsg(xdrs, &msg)) {
- if ((msg.rm_xid == xid) &&
- (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
- (msg.acpted_rply.ar_stat == SUCCESS)) {
- raddr.sin_port = htons((u_short)port);
- done = (*eachresult)(resultsp, &raddr);
- }
- /* otherwise, we just ignore the errors ... */
- }
- xdrs->x_op = XDR_FREE;
- msg.acpted_rply.ar_results.proc = 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;
- }
- }
-done_broad:
- if (fds != &readfds)
- free(fds);
- if (sock >= 0)
- (void)_close(sock);
- AUTH_DESTROY(unix_auth);
- return (stat);
-}
-
diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3
index e2c73cf88de5..fdd28512fd4e 100644
--- a/lib/libc/rpc/rpc.3
+++ b/lib/libc/rpc/rpc.3
@@ -1,1519 +1,507 @@
-.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" @(#)rpc.3n 1.31 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" $NetBSD: rpc.3,v 1.10 2000/06/02 23:11:12 fvdl Exp $
.\" $FreeBSD$
-.\"
-.Dd February 16, 1988
+.Dd May 7, 1993
.Dt RPC 3
.Os
.Sh NAME
.Nm rpc
-.Nd "library routines for remote procedure calls"
+.Nd library routines for remote procedure calls
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.Fd "#include <rpc/rpc.h>"
-.Pp
-See
-.Sx DESCRIPTION
-for function declarations.
+.Fd #include <rpc/rpc.h>
+.Fd #include <netconfig.h>
.Sh DESCRIPTION
-These routines allow C programs to make procedure
-calls on other machines across the network.
-First, the client calls a procedure to send a
-data packet to the server.
-Upon receipt of the packet, the server calls a dispatch routine
-to perform the requested service, and then sends back a
-reply.
-Finally, the procedure call returns to the client.
-.Pp
-Routines that are used for Secure
-.Tn RPC ( DES
-authentication) are described in
-.Xr rpc_secure 3 .
-Secure
-.Tn RPC
-can be used only if
-.Tn DES
-encryption is available.
-.Bl -tag -width indent -compact
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn auth_destroy "AUTH *auth"
-.Xc
-.Pp
-A 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 .
-.Pp
-.It Xo
-.Ft "AUTH *"
-.Xc
-.It Xo
-.Fn authnone_create
-.Xc
-.Pp
-Create and return an
-.Tn RPC
-authentication handle that passes nonusable authentication
-information with each remote procedure call.
-This is the
-default authentication used by
-.Tn RPC .
-.Pp
-.It Xo
-.Ft "AUTH *"
-.Xc
-.It Xo
-.Fn authunix_create "char *host" "int uid" "int gid" "int len" "int *aup_gids"
-.Xc
-.Pp
-Create and return an
-.Tn RPC
-authentication handle that contains
-.Ux
-authentication information.
-The parameter
-.Fa host
-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 is easy to impersonate a user.
-.Pp
-.It Xo
-.Ft "AUTH *"
-.Xc
-.It Xo
-.Fn authunix_create_default
-.Xc
-.Pp
-Calls
-.Fn authunix_create
-with the appropriate parameters.
-.Pp
-.It Xo
-.Fo callrpc
-.Fa "char *host"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "u_long procnum"
-.Fa "xdrproc_t inproc"
-.Fa "char *in"
-.Fa "xdrproc_t outproc"
-.Fa "char *out"
-.Fc
-.Xc
-.Pp
-Call the remote procedure associated with
-.Fa prognum ,
-.Fa versnum ,
-and
-.Fa procnum
-on the machine
-.Fa host .
-The parameter
-.Fa in
-is the address of the procedure's argument(s), and
-.Fa out
-is the address of where to place the result(s);
-.Fa inproc
-is used to encode the procedure's parameters, and
-.Fa outproc
-is used to decode the procedure's results.
-This routine returns zero if it succeeds, or the value of
-.Vt "enum clnt_stat"
-cast to an integer if it fails.
-The routine
-.Fn clnt_perrno
-is handy for translating failure statuses into messages.
-.Pp
-Warning: calling remote procedures with this routine
-uses
-.Tn UDP/IP
-as a transport; see
-.Fn clntudp_create
-for restrictions.
-You do not have control of timeouts or authentication using
-this routine.
-.Pp
-.It Xo
-.Ft "enum clnt_stat"
-.Xc
-.It Xo
-.Fo clnt_broadcast
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "u_long procnum"
-.Fa "xdrproc_t inproc"
-.Fa "char *in"
-.Fa "xdrproc_t outproc"
-.Fa "char *out"
-.Fa "bool_t (*eachresult)(caddr_t, struct sockaddr_in *)
-.Fc
-.Xc
-.Pp
-Like
-.Fn callrpc ,
-except the call message is broadcast to all locally
-connected broadcast nets.
-Each time it receives a
-response, this routine calls
-.Fn eachresult ,
-whose form is:
-.Bd -ragged -offset indent
-.Ft bool_t
-.Fn eachresult "caddr_t out" "struct sockaddr_in *addr"
-.Ed
-.Pp
-where
-.Fa out
-is the same as
-.Fa out
-passed to
-.Fn clnt_broadcast ,
-except that the remote procedure's output is decoded there;
-.Fa addr
-points to the address of the machine that sent the results.
-If
-.Fn eachresult
-returns zero,
-.Fn clnt_broadcast
-waits for more replies; otherwise it returns with appropriate
-status.
-.Pp
-Warning: broadcast sockets are limited in size to the
-maximum transfer unit of the data link.
-For ethernet,
-this value is 1500 bytes.
-.Pp
-.It Xo
-.Ft "enum clnt_stat"
-.Xc
-.It Xo
-.Fo clnt_call
-.Fa "CLIENT *clnt"
-.Fa "u_long procnum"
-.Fa "xdrproc_t inproc"
-.Fa "char *in"
-.Fa "xdrproc_t outproc"
-.Fa "char *out"
-.Fa "struct timeval tout"
-.Fc
-.Xc
-.Pp
-A macro that calls the remote procedure
-.Fa procnum
-associated with the client handle,
-.Fa clnt ,
-which is obtained with an
-.Tn RPC
-client creation routine such as
-.Fn clnt_create .
-The parameter
-.Fa in
-is the address of the procedure's argument(s), and
-.Fa out
-is the address of where to place the result(s);
-.Fa inproc
-is used to encode the procedure's parameters, and
-.Fa outproc
-is used to decode the procedure's results;
-.Fa tout
-is the time allowed for results to come back.
-.Pp
-.It Xo
-.Ft void
-.Fn clnt_destroy "CLIENT *clnt"
-.Xc
-.Pp
-A macro that destroys the client's
-.Tn 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
-.Tn RPC
-library opened the associated socket, it will close it also.
-Otherwise, the socket remains open.
-.Pp
-.It Xo
-.Ft CLIENT *
-.Xc
-.It Xo
-.Fn clnt_create "char *host" "u_long prog" "u_long vers" "char *proto"
-.Xc
-.Pp
-Generic client creation routine.
-.Fa host
-identifies the name of the remote host where the server
-is located.
-.Fa proto
-indicates which kind of transport protocol to use.
-The
-currently supported values for this field are
-.Qq Li udp
-and
-.Qq Li tcp .
-Default timeouts are set, but can be modified using
-.Fn clnt_control .
-.Pp
-Warning: Using
-.Tn UDP
-has its shortcomings.
-Since
-.Tn UDP Ns \-based
-.Tn RPC
-messages can only hold up to 8 Kbytes of encoded data,
-this transport cannot be used for procedures that take
-large arguments or return huge results.
-.Pp
-.It Xo
-.Ft bool_t
-.Xc
-.It Xo
-.Fn clnt_control "CLIENT *cl" "u_int req" "char *info"
-.Xc
-.Pp
-A macro used to change or retrieve various information
-about a client object.
-.Fa req
-indicates the type of operation, and
-.Fa info
-is a pointer to the information.
-For both
-.Tn UDP
-and
-.Tn TCP ,
-the supported values of
-.Fa req
-and their argument types and what they do are:
-.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
-.It Dv CLSET_TIMEOUT Ta Xo
-.Vt "struct timeval" Ta "set total timeout"
-.Xc
-.It Dv CLGET_TIMEOUT Ta Xo
-.Vt "struct timeval" Ta "get total timeout"
-.Xc
-.El
-.Pp
-Note: if you set the timeout using
-.Fn clnt_control ,
-the timeout parameter passed to
-.Fn clnt_call
-will be ignored in all future calls.
-.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
-.It Dv CLGET_SERVER_ADDR Ta Xo
-.Vt "struct sockaddr_in" Ta "get server's address"
-.Xc
-.El
-.Pp
-The following operations are valid for
-.Tn UDP
-only:
-.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
-.It Dv CLSET_RETRY_TIMEOUT Ta Xo
-.Vt "struct timeval" Ta "set the retry timeout"
-.Xc
-.It Dv CLGET_RETRY_TIMEOUT Ta Xo
-.Vt "struct timeval" Ta "get the retry timeout"
-.Xc
-.El
-.Pp
-The retry timeout is the time that
-.Tn "UDP RPC"
-waits for the server to reply before
-retransmitting the request.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn clnt_freeres "CLIENT *clnt" "xdrproc_t outproc" "char *out"
-.Xc
-.Pp
-A macro that frees any data allocated by the
-.Tn RPC/XDR
-system when it decoded the results of an
-.Tn RPC
-call.
-The parameter
-.Fa out
-is the address of the results, and
-.Fa outproc
-is the
-.Tn XDR
-routine describing the results.
-This routine returns one if the results were successfully
-freed,
-and zero otherwise.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn clnt_geterr "CLIENT *clnt" "struct rpc_err *errp"
-.Xc
-.Pp
-A macro that copies the error structure out of the client
-handle
-to the structure at address
-.Fa errp .
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn clnt_pcreateerror "char *s"
-.Xc
-.Pp
-prints a message to standard error indicating
-why a client
-.Tn RPC
-handle could not be created.
-The message is prepended with string
-.Fa s
-and a colon.
-Used when a
+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
+.Aq Pa rpc/rpc.h .
+Routines that take a
+.Vt "struct netconfig"
+also require that
+.Aq Pa netconfig.h
+be included.
+.Sh Nettype
+Some of the high-level
+RPC interface routines take a
+.Fa nettype
+string as one of the parameters
+(for example,
.Fn clnt_create ,
-.Fn clntraw_create ,
-.Fn clnttcp_create ,
-or
-.Fn clntudp_create
-call fails.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn clnt_perrno "enum clnt_stat stat"
-.Xc
-.Pp
-Print a message to standard error corresponding
-to the condition indicated by
-.Fa stat .
-Used after
-.Fn callrpc .
-.Pp
-.It Xo
-.Ft void
-.Fn clnt_perror "CLIENT *clnt" "char *s"
-.Xc
-.Pp
-Print a message to standard error indicating why an
-.Tn RPC
-call failed;
-.Fa clnt
-is the handle used to do the call.
-The message is prepended with string
-.Fa s
-and a colon.
-Used after
-.Fn clnt_call .
-.Pp
-.It Xo
-.Ft "char *"
-.Xc
-.It Xo
-.Fn clnt_spcreateerror "char *s"
-.Xc
-.Pp
-Like
-.Fn clnt_pcreateerror ,
-except that it returns a string
-instead of printing to the standard error.
-.Pp
-Bugs: returns pointer to static data that is overwritten
-on each call.
-.Pp
-.It Xo
-.Ft "char *"
-.Xc
-.It Xo
-.Fn clnt_sperrno "enum clnt_stat stat"
-.Xc
-.Pp
-Take the same arguments as
-.Fn clnt_perrno ,
-but instead of sending a message to the standard error
-indicating why an
-.Tn RPC
-call failed, return a pointer to a string which contains
-the message.
-The string ends with a newline
-.Pq Ql "\en" .
-.Pp
-.Fn clnt_sperrno
-is used instead of
-.Fn clnt_perrno
-if 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 ,
-or if a message format different from that supported by
-.Fn clnt_perrno
-is to be used.
-.Pp
-Note: unlike
-.Fn clnt_sperror
-and
-.Fn clnt_spcreaterror ,
-.Fn clnt_sperrno
-returns pointer to static data, but the
-result will not get overwritten on each call.
-.Pp
-.It Xo
-.Ft "char *"
-.Xc
-.It Xo
-.Fn clnt_sperror "CLIENT *rpch" "char *s"
-.Xc
-.Pp
-Like
-.Fn clnt_perror ,
-except that (like
-.Fn clnt_sperrno )
-it returns a string instead of printing to standard error.
-.Pp
-Bugs: returns pointer to static data that is overwritten
-on each call.
-.Pp
-.It Xo
-.Ft "CLIENT *"
-.Xc
-.It Xo
-.Fn clntraw_create "u_long prognum" "u_long versnum"
-.Xc
-.Pp
-This routine creates a toy
-.Tn RPC
-client for the remote program
-.Fa prognum ,
-version
-.Fa versnum .
-The transport used to pass messages to the service is
-actually a buffer within the process's address space, so the
-corresponding
-.Tn RPC
-server should live in the same address space; see
-.Fn svcraw_create .
-This allows simulation of
-.Tn RPC
-and acquisition of
-.Tn RPC
-overheads, such as round trip times, without any
-kernel interference.
-This routine returns
-.Dv NULL
-if it fails.
-.Pp
-.It Xo
-.Ft "CLIENT *"
-.Xc
-.It Xo
-.Fo clnttcp_create
-.Fa "struct sockaddr_in *addr"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "int *sockp"
-.Fa "u_int sendsz"
-.Fa "u_int recvsz"
-.Fc
-.Xc
-.Pp
-This routine creates an
-.Tn RPC
-client for the remote program
-.Fa prognum ,
-version
-.Fa versnum ;
-the client uses
-.Tn TCP/IP
-as a transport.
-The remote program is located at Internet
-address
-.Fa addr .
-If
-.Fa addr\->sin_port
-is zero, then it is set to the actual port that the remote
-program is listening on (the remote
-.Xr portmap 8
-service is consulted for this information).
-The parameter
-.Fa sockp
-is a socket; if it is
-.Dv RPC_ANYSOCK ,
-then this routine opens a new one and sets
-.Fa sockp .
-Since
-.Tn TCP Ns \-based
-.Tn RPC
-uses buffered
-.Tn I/O ,
-the user may specify the size of the send and receive buffers
-with the parameters
-.Fa sendsz
-and
-.Fa recvsz ;
-values of zero choose suitable defaults.
-This routine returns
-.Dv NULL
-if it fails.
-.Pp
-.It Xo
-.Ft "CLIENT *"
-.Xc
-.It Xo
-.Fo clntudp_create
-.Fa "struct sockaddr_in *addr"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "struct timeval wait"
-.Fa "int *sockp"
-.Fc
-.Xc
-.Pp
-This routine creates an
-.Tn RPC
-client for the remote program
-.Fa prognum ,
-version
-.Fa versnum ;
-the client uses
-.Tn UDP/IP
-as a transport.
-The remote program is located at Internet
-address
-.Fa addr .
-If
-.Fa addr\->sin_port
-is zero, then it is set to actual port that the remote
-program is listening on (the remote
-.Xr portmap 8
-service is consulted for this information).
-The parameter
-.Fa sockp
-is a socket; if it is
-.Dv RPC_ANYSOCK ,
-then this routine opens a new one and sets
-.Fa sockp .
-The
-.Tn UDP
-transport resends the call message in intervals of
-.Fa wait
-time 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 .
-.Pp
-Warning: since
-.Tn UDP Ns \-based
-.Tn RPC
-messages can only hold up to 8 Kbytes
-of encoded data, this transport cannot be used for procedures
-that take large arguments or return huge results.
-.Pp
-.It Xo
-.Ft "CLIENT *"
-.Xc
-.It Xo
-.Fo clntudp_bufcreate
-.Fa "struct sockaddr_in *addr"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "struct timeval wait"
-.Fa "int *sockp"
-.Fa "unsigned int sendsize"
-.Fa "unsigned int recosize"
-.Fc
-.Xc
-.Pp
-This routine creates an
-.Tn RPC
-client for the remote program
-.Fa prognum ,
-on
-.Fa versnum ;
-the client uses
-.Tn UDP/IP
-as a transport.
-The remote program is located at Internet
-address
-.Fa addr .
-If
-.Fa addr\->sin_port
-is zero, then it is set to actual port that the remote
-program is listening on (the remote
-.Xr portmap 8
-service is consulted for this information).
-The parameter
-.Fa sockp
-is a socket; if it is
-.Dv RPC_ANYSOCK ,
-then this routine opens a new one and sets
-.Fa sockp .
-The
-.Tn UDP
-transport resends the call message in intervals of
-.Fa wait
-time 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 .
-.Pp
-This allows the user to specify the maximum packet size
-for sending and receiving
-.Tn UDP Ns \-based
-.Tn RPC
-messages.
-.Pp
-.It Xo
-.Ft int
-.Xc
-.It Xo
-.Fn get_myaddress "struct sockaddr_in *addr"
-.Xc
-.Pp
-Stuff the machine's
-.Tn IP
-address into
-.Fa addr ,
-without consulting the library routines that deal with
-.Pa /etc/hosts .
-The port number is always set to
-.Fn htons PMAPPORT .
-Returns zero on success, non-zero on failure.
-.Pp
-.It Xo
-.Ft "struct pmaplist *"
-.Xc
-.It Xo
-.Fn pmap_getmaps "struct sockaddr_in *addr"
-.Xc
-.Pp
-A user interface to the
-.Xr portmap 8
-service, which returns a list of the current
-.Tn RPC
-program\-to\-port mappings
-on the host located at
-.Tn IP
-address
-.Fa addr .
-This routine can return
-.Dv NULL .
-The command
-.Dq Nm rpcinfo Fl p
-uses this routine.
-.Pp
-.It Xo
-.Ft u_short
-.Xc
-.It Xo
-.Fo pmap_getport
-.Fa "struct sockaddr_in *addr"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "u_long protocol"
-.Fc
-.Xc
-.Pp
-A user interface to the
-.Xr portmap 8
-service, which returns the port number
-on which waits a service that supports program number
-.Fa prognum ,
-version
-.Fa versnum ,
-and speaks the transport protocol associated with
-.Fa protocol .
-The value of
-.Fa protocol
-is most likely
-.Dv IPPROTO_UDP
+.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
+.Fa nettype
+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
-.Dv IPPROTO_TCP .
-A return value of zero means that the mapping does not exist
-or that
-the
-.Tn RPC
-system failed to contact the remote
-.Xr portmap 8
-service.
-In the latter case, the global variable
-.Va rpc_createerr
-contains the
-.Tn RPC
-status.
-.Pp
-.It Xo
-.Ft "enum clnt_stat"
-.Xc
-.It Xo
-.Fo pmap_rmtcall
-.Fa "struct sockaddr_in *addr"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "u_long procnum"
-.Fa "xdrproc_t inproc"
-.Fa "char *in"
-.Fa "xdrproc_t outproc"
-.Fa "char *out"
-.Fa "struct timeval tout"
-.Fa "u_long *portp"
-.Fc
-.Xc
-.Pp
-A user interface to the
-.Xr portmap 8
-service, which instructs
-.Xr portmap 8
-on the host at
-.Tn IP
-address
-.Fa addr
-to make an
-.Tn RPC
-call on your behalf to a procedure on that host.
-The parameter
-.Fa portp
-will be modified to the program's port number if the
-procedure
-succeeds.
-The definitions of other parameters are discussed
-in
-.Fn callrpc
-and
-.Fn clnt_call .
-This procedure should be used for a
-.Dq ping
-and nothing
-else.
-See also
-.Fn clnt_broadcast .
-.Pp
-.It Xo
-.Ft bool_t
-.Fn pmap_set "u_long prognum" "u_long versnum" "u_long protocol" "u_short port"
-.Xc
-.Pp
-A user interface to the
-.Xr portmap 8
-service, which establishes a mapping between the triple
-.Pq Fa prognum , versnum , protocol
-and
-.Fa port
-on the machine's
-.Xr portmap 8
-service.
-The value of
-.Fa protocol
-is most likely
-.Dv IPPROTO_UDP
+.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
-.Dv IPPROTO_TCP .
-This routine returns one if it succeeds, zero otherwise.
-Automatically done by
-.Fn svc_register .
-.Pp
-.It Xo
-.Ft bool_t
-.Fn pmap_unset "u_long prognum" "u_long versnum"
-.Xc
-.Pp
-A user interface to the
-.Xr portmap 8
-service, which destroys all mapping between the triple
-.Pq Fa prognum , versnum , *
-and
-.Fa ports
-on the machine's
-.Xr portmap 8
-service.
-This routine returns one if it succeeds, zero
-otherwise.
-.Pp
-.It Xo
-.Ft bool_t
-.Fo registerrpc
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "u_long procnum"
-.Fa "char *(*procname)(void)"
-.Fa "xdrproc_t inproc"
-.Fa "xdrproc_t outproc"
-.Fc
-.Xc
-.Pp
-Register procedure
-.Fa procname
-with the
-.Tn 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 parameter(s);
-.Fa progname
-should return a pointer to its static result(s);
-.Fa inproc
-is used to decode the parameters while
-.Fa outproc
-is used to encode the results.
-This routine returns zero if the registration succeeded, \-1
-otherwise.
-.Pp
-Warning: remote procedures registered in this form
-are accessed using the
-.Tn UDP/IP
-transport; see
-.Fn svcudp_create
-for restrictions.
-.Pp
-.It Xo
-.Vt "struct rpc_createerr" rpc_createerr ;
-.Xc
-.Pp
-A global variable whose value is set by any
-.Tn RPC
-client creation routine
-that does not succeed.
-Use the routine
-.Fn clnt_pcreateerror
-to print the reason why.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn svc_destroy "SVCXPRT * xprt"
-.Xc
-.Pp
-A macro that destroys the
-.Tn RPC
-service transport 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.
-.Pp
-.It Xo
-.Vt fd_set svc_fdset ;
-.Xc
-.Pp
-A global variable reflecting the
-.Tn RPC
-service side's
-read file descriptor bit mask; it is suitable as a template parameter
-to the
-.Xr select 2
-system call.
-This is only of interest
-if a service implementor does not call
-.Fn svc_run ,
-but rather does his 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.
-As well, note that if the process has descriptor limits
-which are extended beyond
-.Dv FD_SETSIZE ,
-this variable will only be usable for the first
-.Dv FD_SETSIZE
-descriptors.
-.Pp
-.It Xo
-.Vt int svc_fds ;
-.Xc
-.Pp
-Similar to
-.Va svc_fdset ,
-but limited to 32 descriptors.
-This
-interface is obsoleted by
-.Va svc_fdset .
-.Pp
-.It Xo
-.Ft bool_t
-.Fn svc_freeargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in"
-.Xc
-.Pp
-A macro that frees any data allocated by the
-.Tn RPC/XDR
-system when it decoded the arguments to a service procedure
-using
-.Fn svc_getargs .
-This routine returns 1 if the results were successfully
-freed,
-and zero otherwise.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn svc_getargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in"
-.Xc
-.Pp
-A macro that decodes the arguments of an
-.Tn RPC
-request
-associated with the
-.Tn RPC
-service transport handle,
-.Fa xprt .
-The parameter
-.Fa in
-is the address where the arguments will be placed;
-.Fa inproc
-is the
-.Tn XDR
-routine used to decode the arguments.
-This routine returns one if decoding succeeds, and zero
-otherwise.
-.Pp
-.It Xo
-.Ft "struct sockaddr_in *"
-.Xc
-.It Xo
-.Fn svc_getcaller "SVCXPRT *xprt"
-.Xc
-.Pp
-The approved way of getting the network address of the caller
-of a procedure associated with the
-.Tn RPC
-service transport handle,
-.Fa xprt .
-.Pp
-.It Xo
-.Ft void
-.Fn svc_getreqset "fd_set *rdfds"
-.Xc
-.Pp
-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 the
-.Xr select 2
-system call has determined that an
-.Tn RPC
-request has arrived on some
-.Tn RPC
-socket(s);
-.Fa rdfds
-is the resultant read file descriptor bit mask.
-The routine returns when all sockets associated with the
-value of
-.Fa rdfds
-have been serviced.
-.Pp
-.It Xo
-.Ft void
-.Fn svc_getreq "int rdfds"
-.Xc
-.Pp
-Similar to
-.Fn svc_getreqset ,
-but limited to 32 descriptors.
-This interface is obsoleted by
-.Fn svc_getreqset .
-.Pp
-.It Xo
-.Ft bool_t
-.Fo svc_register
-.Fa "SVCXPRT *xprt"
-.Fa "u_long prognum"
-.Fa "u_long versnum"
-.Fa "void (*dispatch)(struct svc_req *, SVCXPRT *)"
-.Fa "int protocol"
-.Fc
-.Xc
+.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
-Associates
-.Fa prognum
-and
-.Fa versnum
-with the service dispatch procedure,
-.Fn dispatch .
If
-.Fa protocol
-is zero, the service is not registered with the
-.Xr portmap 8
-service.
-If
-.Fa protocol
-is non-zero, then a mapping of the triple
-.Pq Fa prognum , versnum , protocol
-to
-.Fa xprt\->xp_port
-is established with the local
-.Xr portmap 8
-service (generally
-.Fa protocol
-is zero,
-.Dv IPPROTO_UDP
-or
-.Dv IPPROTO_TCP ) .
-The procedure
-.Fn dispatch
-has the following form:
-.Bd -ragged -offset indent
-.Ft bool_t
-.Fn dispatch "struct svc_req *request" "SVCXPRT *xprt"
+.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
-.Pp
-The
-.Fn svc_register
-routine returns one if it succeeds, and zero otherwise.
-.Pp
-.It Xo
-.Fn svc_run
-.Xc
-.Pp
-This routine never returns.
-It waits for
-.Tn RPC
-requests to arrive, and calls the appropriate service
-procedure using
-.Fn svc_getreq
-when one arrives.
-This procedure is usually waiting for a
-.Xr select 2
-system call to return.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "char *out"
-.Xc
-.Pp
-Called by an
-.Tn RPC
-service's dispatch routine to send the results of a
-remote procedure call.
-The parameter
-.Fa xprt
-is the request's associated transport handle;
-.Fa outproc
-is the
-.Tn XDR
-routine which is used to encode the results; and
-.Fa out
-is the address of the results.
-This routine returns one if it succeeds, zero otherwise.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svc_unregister "u_long prognum" "u_long versnum"
-.Xc
-.Pp
-Remove all mapping of the double
-.Pq Fa prognum , versnum
-to dispatch routines, and of the triple
-.Pq Fa prognum , versnum , *
-to port number.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why"
-.Xc
-.Pp
-Called by a service dispatch routine that refuses to perform
-a remote procedure call due to an authentication error.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_decode "SVCXPRT *xprt"
-.Xc
-.Pp
-Called by a service dispatch routine that cannot successfully
-decode its parameters.
-See also
-.Fn svc_getargs .
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_noproc "SVCXPRT *xprt"
-.Xc
-.Pp
-Called by a service dispatch routine that does not implement
-the procedure number that the caller requests.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_noprog "SVCXPRT *xprt"
-.Xc
-.Pp
-Called when the desired program is not registered with the
-.Tn RPC
-package.
-Service implementors usually do not need this routine.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_progvers "SVCXPRT *xprt" "u_long low_vers" "u_long high_vers"
-.Xc
-.Pp
-Called when the desired version of a program is not registered
-with the
-.Tn RPC
-package.
-Service implementors usually do not need this routine.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_systemerr "SVCXPRT *xprt"
-.Xc
-.Pp
-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.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn svcerr_weakauth "SVCXPRT *xprt"
-.Xc
-.Pp
-Called by a service dispatch routine that refuses to perform
-a remote procedure call due to insufficient
-authentication parameters.
-The routine calls
-.Fn svcerr_auth xprt AUTH_TOOWEAK .
-.Pp
-.It Xo
-.Ft "SVCXPRT *"
-.Xc
-.It Xo
-.Fn svcraw_create void
-.Xc
-.Pp
-This routine creates a toy
-.Tn RPC
-service transport, to which it returns a pointer.
-The transport
-is really a buffer within the process's address space,
-so the corresponding
-.Tn RPC
-client should live in the same
-address space;
-see
-.Fn clntraw_create .
-This routine allows simulation of
-.Tn RPC
-and acquisition of
-.Tn RPC
-overheads (such as round trip times), without any kernel
-interference.
-This routine returns
-.Dv NULL
-if it fails.
-.Pp
-.It Xo
-.Ft "SVCXPRT *"
-.Xc
-.It Xo
-.Fn svctcp_create "int sock" "u_int send_buf_size" "u_int recv_buf_size"
-.Xc
-.Pp
-This routine creates a
-.Tn TCP/IP Ns \-based
-.Tn RPC
-service transport, to which it returns a pointer.
-The transport is associated with the socket
-.Fa sock ,
-which may be
-.Dv RPC_ANYSOCK ,
-in which case a new socket is created.
-If the socket is not bound to a local
-.Tn TCP
-port, then this routine binds it to an arbitrary port.
-Upon completion,
-.Fa xprt\->xp_sock
-is the transport's socket descriptor, and
-.Fa xprt\->xp_port
-is the transport's port number.
-This routine returns
-.Dv NULL
-if it fails.
-Since
-.Tn TCP Ns \-based
-.Tn RPC
-uses buffered
-.Tn I/O ,
-users may specify the size of buffers; values of zero
-choose suitable defaults.
-.Pp
-.It Xo
-.Ft "SVCXPRT *"
-.Xc
-.It Xo
-.Fn svcfd_create "int fd" "u_int sendsize" "u_int recvsize"
-.Xc
-.Pp
-Create a service on top of any open descriptor.
-Typically,
-this
-descriptor is a connected socket for a stream protocol such
-as
-.Tn TCP .
-.Fa sendsize
-and
-.Fa recvsize
-indicate sizes for the send and receive buffers.
-If they are
-zero, a reasonable default is chosen.
-.Pp
-.It Xo
-.Ft "SVCXPRT *"
-.Xc
-.It Xo
-.Fn svcudp_bufcreate "int sock" "u_int sendsize" "u_int recvsize"
-.Xc
-.Pp
-This routine creates a
-.Tn UDP/IP Ns \-based
-.Tn RPC
-service transport, to which it returns a pointer.
-The transport is associated with the socket
-.Fa sock ,
-which may be
-.Dv RPC_ANYSOCK ,
-in which case a new socket is created.
-If the socket is not bound to a local
-.Tn UDP
-port, then this routine binds it to an arbitrary port.
-Upon
-completion,
-.Fa xprt\->xp_sock
-is the transport's socket descriptor, and
-.Fa xprt\->xp_port
-is the transport's port number.
-This routine returns
-.Dv NULL
-if it fails.
-.Pp
-This allows the user to specify the maximum packet size for sending and
-receiving
-.Tn UDP Ns \-based
-.Tn RPC
-messages.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar"
-.Xc
-.Pp
-Used for encoding
-.Tn RPC
-reply messages.
-This routine is useful for users who
-wish to generate
-.Tn RPC Ns \-style
-messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_authunix_parms "XDR *xdrs" "struct authunix_parms *aupp"
-.Xc
-.Pp
-Used for describing
-.Ux
-credentials.
-This routine is useful for users
-who wish to generate these credentials without using the
-.Tn RPC
-authentication package.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Ft bool_t
-.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr"
-.Xc
-.Pp
-Used for describing
-.Tn RPC
-call header messages.
-This routine is useful for users who wish to generate
-.Tn RPC Ns \-style
-messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg"
-.Xc
-.Pp
-Used for describing
-.Tn RPC
-call messages.
-This routine is useful for users who wish to generate
-.Tn RPC Ns \-style
-messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap"
-.Xc
-.Pp
-Used for describing
-.Tn RPC
-authentication information messages.
-This routine is useful for users who wish to generate
-.Tn RPC Ns \-style
-messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Vt struct pmap ;
-.Xc
-.It Xo
-.Ft bool_t
-.Fn xdr_pmap "XDR *xdrs" "struct pmap *regs"
-.Xc
-.Pp
-Used for describing parameters to various
-.Xr portmap 8
-procedures, externally.
-This routine is useful for users who wish to generate
-these parameters without using the
-.Fn pmap_*
-interface.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_pmaplist "XDR *xdrs" "struct pmaplist **rp"
-.Xc
-.Pp
-Used for describing a list of port mappings, externally.
-This routine is useful for users who wish to generate
-these parameters without using the
-.Fn pmap_*
-interface.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr"
-.Xc
-.Pp
-Used for describing
-.Tn RPC
-reply messages.
-This routine is useful for users who wish to generate
-.Tn RPC Ns \-style
-messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Ft bool_t
-.Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg"
-.Xc
-.Pp
-Used for describing
-.Tn RPC
-reply messages.
-This routine is useful for users who wish to generate
-.Tn RPC
-style messages without using the
-.Tn RPC
-package.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn xprt_register "SVCXPRT *xprt"
-.Xc
-.Pp
-After
-.Tn RPC
-service transport handles are created,
-they should register themselves with the
-.Tn RPC
-service package.
-This routine modifies the global variable
-.Va svc_fds .
-Service implementors usually do not need this routine.
-.Pp
-.It Xo
-.Ft void
-.Xc
-.It Xo
-.Fn xprt_unregister "SVCXPRT *xprt"
-.Xc
-.Pp
-Before an
-.Tn RPC
-service transport handle is destroyed,
-it should unregister itself with the
-.Tn RPC
-service package.
-This routine modifies the global variable
-.Va svc_fds .
-Service implementors usually do not need this routine.
+.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 */
+ 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 addres 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_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_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 rpc_secure 3 ,
-.Xr xdr 3
-.Rs
-.%T "Remote Procedure Calls: Protocol Specification"
-.Re
-.Rs
-.%T "Remote Procedure Call Programming Guide"
-.Re
-.Rs
-.%T "rpcgen Programming Guide"
-.Re
-.Rs
-.%T "RPC: Remote Procedure Call Protocol Specification"
-.%O RFC1050
-.%Q "Sun Microsystems, Inc., USC-ISI"
-.Re
+.Xr getnetconfig 3 ,
+.Xr getnetpath 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 rpcbind 3 ,
+.Xr xdr 3 ,
+.Xr netconfig 5
diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5
index 8a45a9979a9d..6cf79f06bd2c 100644
--- a/lib/libc/rpc/rpc.5
+++ b/lib/libc/rpc/rpc.5
@@ -1,36 +1,60 @@
+.\" $NetBSD: rpc.5,v 1.3 2000/06/15 20:05:54 fvdl Exp $
.\" $FreeBSD$
-.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI;
-.Dd September 26, 1985
+.\" $FreeBSD$
+.\" @(#)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
-/etc/rpc
+.Pa /etc/rpc
.Sh DESCRIPTION
The
-.Pa /etc/rpc
+.Nm
file contains user readable names that
-can be used in place of rpc program numbers.
-Each line has the following information:
+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 -bullet -compact
+.Bl -enum -compact
.It
-name of server for the rpc program
+name of the RPC program
.It
-rpc program number
+RPC program number
.It
aliases
.El
.Pp
Items are separated by any number of blanks and/or
tab characters.
-A ``#'' indicates the beginning of a comment; characters up to the end of
+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 -compact -width /etc/rpc
-.It Pa /etc/rpc
+.Bl -tag -width /etc/nsswitch.conf -compact
+.It Pa /etc/nsswitch.conf
.El
-.Sh "SEE ALSO"
+.Sh SEE ALSO
.Xr getrpcent 3
diff --git a/lib/libc/rpc/rpc_callmsg.c b/lib/libc/rpc/rpc_callmsg.c
index dca3a1880d93..827fd3eb7caf 100644
--- a/lib/libc/rpc/rpc_callmsg.c
+++ b/lib/libc/rpc/rpc_callmsg.c
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc_callmsg.c,v 1.16 2000/07/14 08:40:42 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -40,21 +43,27 @@ static char *rcsid = "$FreeBSD$";
*
*/
-#include <sys/param.h>
+#include "namespace.h"
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
+
#include <rpc/rpc.h>
+#include "un-namespace.h"
/*
* XDR a call message
*/
bool_t
xdr_callmsg(xdrs, cmsg)
- register XDR *xdrs;
- register struct rpc_msg *cmsg;
+ XDR *xdrs;
+ struct rpc_msg *cmsg;
{
- register int32_t *buf;
- register struct opaque_auth *oa;
+ 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) {
@@ -68,30 +77,30 @@ xdr_callmsg(xdrs, cmsg)
+ 2 * BYTES_PER_XDR_UNIT
+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
if (buf != NULL) {
- IXDR_PUT_LONG(buf, cmsg->rm_xid);
+ IXDR_PUT_INT32(buf, cmsg->rm_xid);
IXDR_PUT_ENUM(buf, cmsg->rm_direction);
if (cmsg->rm_direction != CALL) {
return (FALSE);
}
- IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+ IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
return (FALSE);
}
- IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
- IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
- IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+ 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_LONG(buf, oa->oa_length);
+ IXDR_PUT_INT32(buf, oa->oa_length);
if (oa->oa_length) {
- memcpy((caddr_t)buf, oa->oa_base, 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_LONG(buf, oa->oa_length);
+ IXDR_PUT_INT32(buf, oa->oa_length);
if (oa->oa_length) {
- memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
+ memmove(buf, oa->oa_base, oa->oa_length);
/* no real need....
buf += RNDUP(oa->oa_length) / sizeof (int32_t);
*/
@@ -102,28 +111,30 @@ xdr_callmsg(xdrs, cmsg)
if (xdrs->x_op == XDR_DECODE) {
buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
if (buf != NULL) {
- cmsg->rm_xid = IXDR_GET_LONG(buf);
+ 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_LONG(buf);
+ 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_LONG(buf);
- cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
- cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+ 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 = IXDR_GET_LONG(buf);
+ 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);
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
}
buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
if (buf == NULL) {
@@ -132,7 +143,7 @@ xdr_callmsg(xdrs, cmsg)
return (FALSE);
}
} else {
- memcpy(oa->oa_base, (caddr_t)buf,
+ memmove(oa->oa_base, buf,
oa->oa_length);
/* no real need....
buf += RNDUP(oa->oa_length) /
@@ -149,7 +160,7 @@ xdr_callmsg(xdrs, cmsg)
}
} else {
oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
- oa->oa_length = IXDR_GET_LONG(buf);
+ oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
}
if (oa->oa_length) {
if (oa->oa_length > MAX_AUTH_BYTES) {
@@ -157,7 +168,9 @@ xdr_callmsg(xdrs, cmsg)
}
if (oa->oa_base == NULL) {
oa->oa_base = (caddr_t)
- mem_alloc(oa->oa_length);
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
}
buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
if (buf == NULL) {
@@ -166,7 +179,7 @@ xdr_callmsg(xdrs, cmsg)
return (FALSE);
}
} else {
- memcpy(oa->oa_base, (caddr_t)buf,
+ memmove(oa->oa_base, buf,
oa->oa_length);
/* no real need...
buf += RNDUP(oa->oa_length) /
@@ -187,7 +200,6 @@ xdr_callmsg(xdrs, cmsg)
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 (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
return (FALSE);
}
-
diff --git a/lib/libc/rpc/rpc_clnt_auth.3 b/lib/libc/rpc/rpc_clnt_auth.3
new file mode 100644
index 000000000000..b3d720b0fae2
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_auth.3
@@ -0,0 +1,95 @@
+.\" @(#)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$
+.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
+.Fd #include <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
+.Fn 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 parameter
+.Fa host
+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 parameters.
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr rpc_clnt_calls 3 ,
+.Xr rpc_clnt_create 3
diff --git a/lib/libc/rpc/rpc_clnt_calls.3 b/lib/libc/rpc/rpc_clnt_calls.3
new file mode 100644
index 000000000000..cd368dd351a3
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_calls.3
@@ -0,0 +1,302 @@
+.\" @(#)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$
+.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
+.Fd #include <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 "const CLIENT * clnt" "const char *s"
+.Ft "char *"
+.Fn clnt_sperrno "const enum clnt_stat stat"
+.Ft "char *"
+.Fn clnt_sperror "const 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 "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 int inittime" "const int waittime"
+.Fa "const resultproc_t eachresult" "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 parameters.
+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 parameter
+.Fa inproc
+is the XDR function used to encode the procedure's parameters, 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).
+.Fa tout
+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 parameter
+.Fa out
+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.
+.Fn clnt_sperrno
+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_spcreaterror
+(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.
+.Fn rpc_broadcast
+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.
+.Fa inittime
+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 parameter
+.Fa inproc
+is used to encode the procedure's parameters, 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).
+.Fa nettype
+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
diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3
new file mode 100644
index 000000000000..e13ac5b86427
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_create.3
@@ -0,0 +1,437 @@
+.\" @(#)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$
+.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_vers ,
+.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_vc_create ,
+.Nm rpc_createerr
+.Nd "library routines for dealing with creation and manipulation of"
+.Vt CLIENT
+handles
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <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_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "char *nettype"
+.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_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const 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.
+.Fa req
+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 parameter 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 "unsigned long *" Ta "get RPC program version"
+.It Dv CLSET_VERS Ta "unsigned long *" Ta "set RPC program version"
+.It Dv CLGET_XID Ta "unsigned long *" Ta "get XID of previous call"
+.It Dv CLSET_XID Ta "unsigned long *" 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"
+.El
+.Pp
+The retry timeout is the time that RPC
+waits for the server to reply before retransmitting the request.
+.Fn clnt_control
+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 .
+.Fa host
+identifies the name of the remote host where the server
+is located.
+.Fa nettype
+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.
+.Fn clnt_create
+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_vers
+Generic client creation routine which is similar to
+.Fn clnt_create
+but which also checks for the
+version availability.
+.Fa host
+identifies the name of the remote host where the server
+is located.
+.Fa nettype
+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.
+.Fa vers_outp
+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_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 parameter
+.Fa fildes
+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 parameters
+.Fa sendsz
+and
+.Fa recvsz ;
+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.
+.Fn clnt_raw_create
+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.
+.Fa fildes
+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 parameters
+.Fa sendsz
+and
+.Fa recvsz ;
+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 .
+.Fn clnt_tp_create
+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_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 parameter
+.Fa fildes
+is an open and bound file descriptor.
+The user may specify the size of the send and receive buffers
+with the parameters
+.Fa sendsz
+and
+.Fa recvsz ;
+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.
+.Fn clnt_vc_create
+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
diff --git a/lib/libc/rpc/rpc_com.h b/lib/libc/rpc/rpc_com.h
new file mode 100644
index 000000000000..8a1269393aff
--- /dev/null
+++ b/lib/libc/rpc/rpc_com.h
@@ -0,0 +1,85 @@
+/* $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * 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 _RPC_RPCCOM_H
+#define _RPC_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
+
+#define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \
+ (u_int32_t)(now)->tv_usec)
+
+__BEGIN_DECLS
+extern u_int __rpc_get_a_size __P((int));
+extern int __rpc_dtbsize __P((void));
+extern struct netconfig * __rpcgettp __P((int));
+extern int __rpc_get_default_domain __P((char **));
+
+char *__rpc_taddr2uaddr_af __P((int, const struct netbuf *));
+struct netbuf *__rpc_uaddr2taddr_af __P((int, const char *));
+int __rpc_fixup_addr __P((struct netbuf *, const struct netbuf *));
+int __rpc_sockinfo2netid __P((struct __rpc_sockinfo *, const char **));
+int __rpc_seman2socktype __P((int));
+int __rpc_socktype2seman __P((int));
+void *rpc_nullproc __P((CLIENT *));
+int __rpc_sockisbound __P((int));
+
+struct netbuf *__rpcb_findaddr __P((rpcprog_t, rpcvers_t,
+ const struct netconfig *,
+ const char *, CLIENT **));
+bool_t __rpc_control __P((int,void *));
+
+char *_get_next_token __P((char *, int));
+
+__END_DECLS
+
+#endif /* _RPC_RPCCOM_H */
diff --git a/lib/libc/rpc/rpc_commondata.c b/lib/libc/rpc/rpc_commondata.c
index 043c08285056..ba5839e6df3f 100644
--- a/lib/libc/rpc/rpc_commondata.c
+++ b/lib/libc/rpc/rpc_commondata.c
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc_commondata.c,v 1.7 2000/06/02 23:11:13 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -5,39 +7,42 @@
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
- *
+ *
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
+ *
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
- *
+ *
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
- *
+ *
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
- *
+ *
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
+#include "namespace.h"
#include <rpc/rpc.h>
+#include "un-namespace.h"
+
/*
* This file should only contain common data (global data) that is exported
- * by public interfaces
+ * by public interfaces
*/
struct opaque_auth _null_auth;
fd_set svc_fdset;
int svc_maxfd = -1;
-struct rpc_createerr rpc_createerr;
diff --git a/lib/libc/rpc/rpc_dtablesize.c b/lib/libc/rpc/rpc_dtablesize.c
index 44b327966039..16e0a2b00305 100644
--- a/lib/libc/rpc/rpc_dtablesize.c
+++ b/lib/libc/rpc/rpc_dtablesize.c
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,14 +29,18 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/
/*static char *sccsid = "from: @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
#endif
-#include <sys/types.h>
+#include "namespace.h"
#include <unistd.h>
+#include "un-namespace.h"
+
+int _rpc_dtablesize __P((void)); /* XXX */
/*
* Cache the result of getdtablesize(), so we don't have to do an
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
new file mode 100644
index 000000000000..790bbc59683f
--- /dev/null
+++ b/lib/libc/rpc/rpc_generic.c
@@ -0,0 +1,816 @@
+/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */
+
+/*
+ * rpc_generic.c, Miscl routines for RPC.
+ *
+ */
+
+#include "reentrant.h"
+#include "namespace.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 <stdio.h>
+#include <netdb.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/nettype.h>
+#include "un-namespace.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;
+ int 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
+ { "unix", AF_LOCAL, 0 }
+};
+
+#if 0
+static char *strlocase __P((char *));
+#endif
+static int getnettype __P((const char *));
+
+/*
+ * Cache the result of getrlimit(), so we don't have to do an
+ * expensive call every time.
+ */
+int
+__rpc_dtbsize()
+{
+ 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);
+}
+
+
+/*
+ * Find the appropriate buffer size
+ */
+u_int
+/*ARGSUSED*/
+__rpc_get_t_size(af, proto, size)
+ int af, proto;
+ int size; /* Size requested */
+{
+ int maxsize;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ maxsize = 65536; /* XXX */
+ break;
+ case IPPROTO_UDP:
+ maxsize = 8192; /* XXX */
+ break;
+ default:
+ maxsize = RPC_MAXDATASIZE;
+ break;
+ }
+ if (size == 0)
+ return maxsize;
+
+ /* Check whether the value is within the upper max limit */
+ return (size > maxsize ? (u_int)maxsize : (u_int)size);
+}
+
+/*
+ * 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
+ case AF_LOCAL:
+ return sizeof (struct sockaddr_un);
+ 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] == NULL)) {
+ 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;
+ static char *netid_tcp_main;
+ static char *netid_udp_main;
+ struct netconfig *dummy;
+ int main_thread;
+ static thread_key_t tcp_key, udp_key;
+ extern mutex_t tsd_lock;
+
+ if ((main_thread = thr_main())) {
+ netid_udp = netid_udp_main;
+ netid_tcp = netid_tcp_main;
+ } else {
+ if (tcp_key == 0) {
+ mutex_lock(&tsd_lock);
+ if (tcp_key == 0)
+ thr_keycreate(&tcp_key, free);
+ mutex_unlock(&tsd_lock);
+ }
+ netid_tcp = (char *)thr_getspecific(tcp_key);
+ if (udp_key == 0) {
+ mutex_lock(&tsd_lock);
+ if (udp_key == 0)
+ 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) {
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ netid_tcp = strdup(nconf->nc_netid);
+ if (main_thread)
+ netid_tcp_main = netid_tcp;
+ else
+ thr_setspecific(tcp_key,
+ (void *) netid_tcp);
+ } else
+ if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
+ netid_udp = strdup(nconf->nc_netid);
+ if (main_thread)
+ netid_udp_main = netid_udp;
+ else
+ 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] == NULL)) {
+ 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)
+ int 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(int fd, struct __rpc_sockinfo *sip)
+{
+ socklen_t len;
+ int type, proto;
+ struct sockaddr_storage ss;
+
+ len = sizeof ss;
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
+ return 0;
+ sip->si_alen = len;
+
+ len = sizeof type;
+ if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+ return 0;
+
+ /* XXX */
+ if (ss.ss_family != AF_LOCAL) {
+ if (type == SOCK_STREAM)
+ proto = IPPROTO_TCP;
+ else if (type == SOCK_DGRAM)
+ proto = IPPROTO_UDP;
+ else
+ return 0;
+ } else
+ proto = 0;
+
+ 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)) {
+ 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;
+}
+
+int
+__rpc_nconf2fd(const struct netconfig *nconf)
+{
+ struct __rpc_sockinfo si;
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return 0;
+
+ return _socket(si.si_af, si.si_socktype, si.si_proto);
+}
+
+int
+__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
+{
+ int i;
+
+ 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 (netid)
+ *netid = na_cvt[i].netid;
+ return 1;
+ }
+
+ 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);
+}
+
+char *
+__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
+{
+ char *ret;
+ struct sockaddr_in *sin;
+ struct sockaddr_un *sun;
+ char namebuf[INET_ADDRSTRLEN];
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+ char namebuf6[INET6_ADDRSTRLEN];
+#endif
+ u_int16_t port;
+
+ 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
+ case AF_LOCAL:
+ sun = nbuf->buf;
+ sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
+ ret = strdup(sun->sun_path);
+ break;
+ default:
+ return NULL;
+ }
+
+ return ret;
+}
+
+struct netbuf *
+__rpc_uaddr2taddr_af(int af, const char *uaddr)
+{
+ struct netbuf *ret = NULL;
+ char *addrstr, *p;
+ unsigned port, portlo, porthi;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+ struct sockaddr_un *sun;
+
+ 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);
+
+ 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;
+ }
+ sin->sin_len = 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(sin);
+ free(ret);
+ ret = NULL;
+ goto out;
+ }
+ sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
+ ret->buf = sin6;
+ break;
+#endif
+ 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);
+ break;
+ 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(int fd)
+{
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
+ return 0;
+
+ switch (ss.ss_family) {
+ case AF_INET:
+ return (((struct sockaddr_in *)
+ (void *)&ss)->sin_port != 0);
+#ifdef INET6
+ case AF_INET6:
+ return (((struct sockaddr_in6 *)
+ (void *)&ss)->sin6_port != 0);
+#endif
+ case AF_LOCAL:
+ /* XXX check this */
+ return (((struct sockaddr_un *)
+ (void *)&ss)->sun_path[0] != '\0');
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/lib/libc/rpc/rpc_prot.c b/lib/libc/rpc/rpc_prot.c
index 940a29d13704..4dbfe19839e3 100644
--- a/lib/libc/rpc/rpc_prot.c
+++ b/lib/libc/rpc/rpc_prot.c
@@ -1,3 +1,5 @@
+/* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";*/
+static char *sccsid = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -46,13 +49,20 @@ static char *rcsid = "$FreeBSD$";
* routines are also in this program.
*/
+#include "namespace.h"
#include <sys/param.h>
+#include <assert.h>
+
#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+static void accepted __P((enum accept_stat, struct rpc_err *));
+static void rejected __P((enum reject_stat, struct rpc_err *));
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
-struct opaque_auth _null_auth;
+extern struct opaque_auth _null_auth;
/*
* XDR an opaque authentication struct
@@ -60,10 +70,13 @@ struct opaque_auth _null_auth;
*/
bool_t
xdr_opaque_auth(xdrs, ap)
- register XDR *xdrs;
- register struct opaque_auth *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));
@@ -75,10 +88,14 @@ xdr_opaque_auth(xdrs, ap)
*/
bool_t
xdr_des_block(xdrs, blkp)
- register XDR *xdrs;
- register des_block *blkp;
+ XDR *xdrs;
+ des_block *blkp;
{
- return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
+
+ assert(xdrs != NULL);
+ assert(blkp != NULL);
+
+ return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
}
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
@@ -88,10 +105,13 @@ xdr_des_block(xdrs, blkp)
*/
bool_t
xdr_accepted_reply(xdrs, ar)
- register XDR *xdrs;
- register struct accepted_reply *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);
@@ -106,7 +126,11 @@ xdr_accepted_reply(xdrs, ar)
if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
return (FALSE);
return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
- default:
+
+ case GARBAGE_ARGS:
+ case SYSTEM_ERR:
+ case PROC_UNAVAIL:
+ case PROG_UNAVAIL:
break;
}
return (TRUE); /* TRUE => open ended set of problems */
@@ -115,12 +139,15 @@ xdr_accepted_reply(xdrs, ar)
/*
* XDR the MSG_DENIED part of a reply message union
*/
-bool_t
+bool_t
xdr_rejected_reply(xdrs, rr)
- register XDR *xdrs;
- register struct rejected_reply *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);
@@ -134,12 +161,14 @@ xdr_rejected_reply(xdrs, rr)
case AUTH_ERROR:
return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
}
+ /* NOTREACHED */
+ assert(0);
return (FALSE);
}
-static struct xdr_discrim reply_dscrm[3] = {
- { (int)MSG_ACCEPTED, xdr_accepted_reply },
- { (int)MSG_DENIED, xdr_rejected_reply },
+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 } };
/*
@@ -147,15 +176,19 @@ static struct xdr_discrim reply_dscrm[3] = {
*/
bool_t
xdr_replymsg(xdrs, rmsg)
- register XDR *xdrs;
- register struct rpc_msg *rmsg;
+ XDR *xdrs;
+ struct rpc_msg *rmsg;
{
+ assert(xdrs != NULL);
+ assert(rmsg != NULL);
+
if (
- xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
+ 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)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
+ (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
+ NULL_xdrproc_t));
return (FALSE);
}
@@ -167,10 +200,13 @@ xdr_replymsg(xdrs, rmsg)
*/
bool_t
xdr_callhdr(xdrs, cmsg)
- register XDR *xdrs;
- register struct rpc_msg *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 (
@@ -179,7 +215,7 @@ xdr_callhdr(xdrs, cmsg)
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 (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
return (FALSE);
}
@@ -187,10 +223,12 @@ xdr_callhdr(xdrs, cmsg)
static void
accepted(acpt_stat, error)
- register enum accept_stat acpt_stat;
- register struct rpc_err *error;
+ enum accept_stat acpt_stat;
+ struct rpc_err *error;
{
+ assert(error != NULL);
+
switch (acpt_stat) {
case PROG_UNAVAIL:
@@ -217,34 +255,35 @@ accepted(acpt_stat, error)
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 = (long)MSG_ACCEPTED;
- error->re_lb.s2 = (long)acpt_stat;
+ error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
+ error->re_lb.s2 = (int32_t)acpt_stat;
}
-static void
+static void
rejected(rjct_stat, error)
- register enum reject_stat rjct_stat;
- register struct rpc_err *error;
+ enum reject_stat rjct_stat;
+ struct rpc_err *error;
{
- switch (rjct_stat) {
+ assert(error != NULL);
- case RPC_VERSMISMATCH:
+ switch (rjct_stat) {
+ case RPC_MISMATCH:
error->re_status = RPC_VERSMISMATCH;
return;
case AUTH_ERROR:
error->re_status = RPC_AUTHERROR;
return;
- default:
- break;
}
/* something's wrong, but we don't know what ... */
+ /* NOTREACHED */
error->re_status = RPC_FAILED;
- error->re_lb.s1 = (long)MSG_DENIED;
- error->re_lb.s2 = (long)rjct_stat;
+ error->re_lb.s1 = (int32_t)MSG_DENIED;
+ error->re_lb.s2 = (int32_t)rjct_stat;
}
/*
@@ -252,10 +291,13 @@ rejected(rjct_stat, error)
*/
void
_seterr_reply(msg, error)
- register struct rpc_msg *msg;
- register struct rpc_err *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) {
@@ -263,7 +305,7 @@ _seterr_reply(msg, error)
if (msg->acpted_rply.ar_stat == SUCCESS) {
error->re_status = RPC_SUCCESS;
return;
- };
+ }
accepted(msg->acpted_rply.ar_stat, error);
break;
@@ -273,7 +315,7 @@ _seterr_reply(msg, error)
default:
error->re_status = RPC_FAILED;
- error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
+ error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
break;
}
switch (error->re_status) {
@@ -291,6 +333,22 @@ _seterr_reply(msg, error)
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;
}
diff --git a/lib/libc/rpc/rpc_soc.3 b/lib/libc/rpc/rpc_soc.3
new file mode 100644
index 000000000000..a915e5743b86
--- /dev/null
+++ b/lib/libc/rpc/rpc_soc.3
@@ -0,0 +1,1810 @@
+.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $
+.\" $FreeBSD$
+.\"
+.TH RPC_SOC 3 "16 February 1988"
+.SH NAME
+rpc_soc,
+auth_destroy,
+authnone_create,
+authunix_create,
+authunix_create_default,
+callrpc,
+clnt_broadcast,
+clnt_call,
+clnt_control,
+clnt_create,
+clnt_destroy,
+clnt_freeres,
+clnt_geterr,
+clnt_pcreateerror,
+clnt_perrno,
+clnt_perror,
+clnt_spcreateerror,
+clnt_sperrno,
+clnt_sperror,
+clntraw_create,
+clnttcp_create,
+clntudp_bufcreate,
+clntudp_create,
+get_myaddress,
+pmap_getmaps,
+pmap_getport,
+pmap_rmtcall,
+pmap_set,
+pmap_unset,
+registerrpc,
+rpc_createerr,
+svc_destroy,
+svc_fds,
+svc_fdset,
+svc_getargs,
+svc_getcaller,
+svc_getreg,
+svc_getregset,
+svc_register,
+svc_run,
+svc_sendreply,
+svc_unregister,
+svcerr_auth,
+svcerr_decode,
+svcerr_noproc,
+svcerr_noprog,
+svcerr_progvers,
+svcerr_systemerr,
+svcerr_weakauth,
+svcfd_create,
+svcraw_create,
+xdr_accepted_reply,
+xdr_authunix_parms,
+xdr_callhdr,
+xdr_callmsg,
+xdr_opaque_auth,
+xdr_pmap,
+xdr_pmaplist,
+xdr_rejected_reply,
+xdr_replymsg,
+xprt_register,
+xprt_unregister \- library routines for remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+.B The svc and clnt functions described in this page are the old, TS-RPC
+.B interface to the XDR and RPC library, and exist
+.B for backward compatibility. The new interface is described in the pages
+.B referenced from
+.BR rpc (3).
+.PP
+These routines allow C programs to make procedure
+calls on other machines across the network.
+First, the client calls a procedure to send a
+data packet to the server.
+Upon receipt of the packet, the server calls a dispatch routine
+to perform the requested service, and then sends back a
+reply.
+Finally, the procedure call returns to the client.
+.\" XXX: NOTYET
+.\".LP
+.\"Routines that are used for Secure RPC (DES authentication) are described in
+.\".BR rpc_secure (3).
+.\"Secure RPC can be used only if DES encryption is available.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+auth_destroy(auth)
+\s-1AUTH\s0 *auth;
+.fi
+.ft R
+.IP
+A macro that destroys the authentication information associated with
+.IR auth .
+Destruction usually involves deallocation of private data
+structures. The use of
+.I auth
+is undefined after calling
+.BR auth_destroy(\|) .
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authnone_create(\|)
+.fi
+.ft R
+.IP
+Create and returns an
+.SM RPC
+authentication handle that passes nonusable authentication
+information with each remote procedure call. This is the
+default authentication used by
+.SM RPC.
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create(host, uid, gid, len, aup_gids)
+char *host;
+int uid, gid, len, *aup.gids;
+.fi
+.ft R
+.IP
+Create and return an
+.SM RPC
+authentication handle that contains
+.UX
+authentication information.
+The parameter
+.I host
+is the name of the machine on which the information was
+created;
+.I uid
+is the user's user
+.SM ID ;
+.I gid
+is the user's current group
+.SM ID ;
+.I len
+and
+.I aup_gids
+refer to a counted array of groups to which the user belongs.
+It is easy to impersonate a user.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create_default(\|)
+.fi
+.ft R
+.IP
+Calls
+.B authunix_create(\|)
+with the appropriate parameters.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+char *host;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Call the remote procedure associated with
+.IR prognum ,
+.IR versnum ,
+and
+.I procnum
+on the machine,
+.IR host .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results.
+This routine returns zero if it succeeds, or the value of
+.B "enum clnt_stat"
+cast to an integer if it fails.
+The routine
+.B clnt_perrno(\|)
+is handy for translating failure statuses into messages.
+.IP
+Warning: calling remote procedures with this routine
+uses
+.SM UDP/IP
+as a transport; see
+.B clntudp_create(\|)
+for restrictions.
+You do not have control of timeouts or authentication using
+this routine.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult)
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+resultproc_t eachresult;
+.fi
+.ft R
+.IP
+Like
+.BR callrpc(\|) ,
+except the call message is broadcast to all locally
+connected broadcast nets. Each time it receives a
+response, this routine calls
+.BR eachresult(\|) ,
+whose form is:
+.IP
+.RS 1i
+.ft B
+.nf
+eachresult(out, addr)
+char *out;
+struct sockaddr_in *addr;
+.ft R
+.fi
+.RE
+.IP
+where
+.I out
+is the same as
+.I out
+passed to
+.BR clnt_broadcast(\|) ,
+except that the remote procedure's output is decoded there;
+.I addr
+points to the address of the machine that sent the results.
+If
+.B eachresult(\|)
+returns zero,
+.B clnt_broadcast(\|)
+waits for more replies; otherwise it returns with appropriate
+status.
+.IP
+Warning: broadcast sockets are limited in size to the
+maximum transfer unit of the data link. For ethernet,
+this value is 1500 bytes.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
+\s-1CLIENT\s0 *clnt;
+u_long
+procnum;
+xdrproc_t inproc, outproc;
+char *in, *out;
+struct timeval tout;
+.fi
+.ft R
+.IP
+A macro that calls the remote procedure
+.I procnum
+associated with the client handle,
+.IR clnt ,
+which is obtained with an
+.SM RPC
+client creation routine such as
+.BR clnt_create(\|) .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results;
+.I tout
+is the time allowed for results to come back.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+clnt_destroy(clnt)
+\s-1CLIENT\s0 *clnt;
+.fi
+.ft R
+.IP
+A macro that destroys the client's
+.SM RPC
+handle. Destruction usually involves deallocation
+of private data structures, including
+.I clnt
+itself. Use of
+.I clnt
+is undefined after calling
+.BR clnt_destroy(\|) .
+If the
+.SM RPC
+library opened the associated socket, it will close it also.
+Otherwise, the socket remains open.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnt_create(host, prog, vers, proto)
+char *host;
+u_long prog, vers;
+char *proto;
+.fi
+.ft R
+.IP
+Generic client creation routine.
+.I host
+identifies the name of the remote host where the server
+is located.
+.I proto
+indicates which kind of transport protocol to use. The
+currently supported values for this field are \(lqudp\(rq
+and \(lqtcp\(rq.
+Default timeouts are set, but can be modified using
+.BR clnt_control(\|) .
+.IP
+Warning: Using
+.SM UDP
+has its shortcomings. Since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes of encoded data,
+this transport cannot be used for procedures that take
+large arguments or return huge results.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+bool_t
+clnt_control(cl, req, info)
+\s-1CLIENT\s0 *cl;
+char *info;
+.fi
+.ft R
+.IP
+A macro used to change or retrieve various information
+about a client object.
+.I req
+indicates the type of operation, and
+.I info
+is a pointer to the information. For both
+.SM UDP
+and
+.SM TCP\s0,
+the supported values of
+.I req
+and their argument types and what they do are:
+.IP
+.nf
+.ta +2.0i +2.0i +2.0i
+.SM CLSET_TIMEOUT\s0 struct timeval set total timeout
+.SM CLGET_TIMEOUT\s0 struct timeval get total timeout
+.fi
+.IP
+Note: if you set the timeout using
+.BR clnt_control(\|) ,
+the timeout parameter passed to
+.B clnt_call(\|)
+will be ignored in all future calls.
+.IP
+.nf
+.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address
+.fi
+.br
+.IP
+The following operations are valid for
+.SM UDP
+only:
+.IP
+.nf
+.ta +2.0i +2.0i +2.0i
+.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout
+.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout
+.fi
+.br
+.IP
+The retry timeout is the time that
+.SM "UDP RPC"
+waits for the server to reply before
+retransmitting the request.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+clnt_freeres(clnt, outproc, out)
+\s-1CLIENT\s0 *clnt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the results of an
+.SM RPC
+call. The
+parameter
+.I out
+is the address of the results, and
+.I outproc
+is the
+.SM XDR
+routine describing the results.
+This routine returns one if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_geterr(clnt, errp)
+\s-1CLIENT\s0 *clnt;
+struct rpc_err *errp;
+.fi
+.ft R
+.IP
+A macro that copies the error structure out of the client
+handle
+to the structure at address
+.IR errp .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_pcreateerror(s)
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating
+why a client
+.SM RPC
+handle could not be created.
+The message is prepended with string
+.I s
+and a colon.
+A
+.SM NEWLINE
+is appended at the end of the message.
+Used when a
+.BR clnt_create(\|) ,
+.BR clntraw_create(\|) ,
+.BR clnttcp_create(\|) ,
+or
+.B clntudp_create(\|)
+call fails.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_perrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Print a message to standard error corresponding
+to the condition indicated by
+.IR stat .
+A
+.SM NEWLINE
+is appended at the end of the message.
+Used after
+.BR callrpc(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+clnt_perror(clnt, s)
+\s-1CLIENT\s0 *clnt;
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating why an
+.SM RPC
+call failed;
+.I clnt
+is the handle used to do the call.
+The message is prepended with string
+.I s
+and a colon.
+A
+.SM NEWLINE
+is appended at the end of the message.
+Used after
+.BR clnt_call(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_spcreateerror
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_pcreateerror(\|) ,
+except that it returns a string
+instead of printing to the standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Take the same arguments as
+.BR clnt_perrno(\|) ,
+but instead of sending a message to the standard error
+indicating why an
+.SM RPC
+call failed, return a pointer to a string which contains
+the message.
+.IP
+.B clnt_sperrno(\|)
+is used instead of
+.B clnt_perrno(\|)
+if 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
+.BR printf ,
+or if a message format different than that supported by
+.B clnt_perrno(\|)
+is to be used.
+Note: unlike
+.B clnt_sperror(\|)
+and
+.BR clnt_spcreateerror(\|) ,
+.B clnt_sperrno(\|)
+returns pointer to static data, but the
+result will not get overwritten on each call.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperror(rpch, s)
+\s-1CLIENT\s0 *rpch;
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_perror(\|) ,
+except that (like
+.BR clnt_sperrno(\|) )
+it returns a string instead of printing to standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntraw_create(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum .
+The transport used to pass messages to the service is
+actually a buffer within the process's address space, so the
+corresponding
+.SM RPC
+server should live in the same address space; see
+.BR svcraw_create(\|) .
+This allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads, such as round trip times, without any
+kernel interference. This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+int *sockp;
+u_int sendsz, recvsz;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM TCP/IP
+as a transport. The remote program is located at Internet
+address
+.IR *addr .
+If
+.\"The following in-line font conversion is necessary for the hyphen indicator
+\fB\%addr\->sin_port\fR
+is zero, then it is set to the actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+the user may specify the size of the send and receive buffers
+with the parameters
+.I sendsz
+and
+.IR recvsz ;
+values of zero choose suitable defaults.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_create(addr, prognum, versnum, wait, sockp)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses use
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+Warning: since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes
+of encoded data, this transport cannot be used for procedures
+that take large arguments or return huge results.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+unsigned int sendsize;
+unsigned int recosize;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+on
+.IR versnum ;
+the client uses use
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.BR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+This allows the user to specify the maximum packet size for sending and
+receiving
+.SM UDP\s0-based
+.SM RPC
+messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+int
+get_myaddress(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+Stuff the machine's
+.SM IP
+address into
+.IR *addr ,
+without consulting the library routines that deal with
+.BR /etc/hosts .
+The port number is always set to
+.BR htons(\s-1PMAPPORT\s0) .
+Returns zero on success, non-zero on failure.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+struct pmaplist *
+pmap_getmaps(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns a list of the current
+.SM RPC
+program-to-port mappings
+on the host located at
+.SM IP
+address
+.IR *addr .
+This routine can return
+.SM NULL .
+The command
+.RB ` "rpcinfo \-p" '
+uses this routine.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+u_short
+pmap_getport(addr, prognum, versnum, protocol)
+struct sockaddr_in *addr;
+u_long prognum, versnum, protocol;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns the port number
+on which waits a service that supports program number
+.IR prognum ,
+version
+.IR versnum ,
+and speaks the transport protocol associated with
+.IR protocol .
+The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+A return value of zero means that the mapping does not exist
+or that
+the
+.SM RPC
+system failured to contact the remote
+.B portmap
+service. In the latter case, the global variable
+.B rpc_createerr(\|)
+contains the
+.SM RPC
+status.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp)
+struct sockaddr_in *addr;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+struct timeval tout;
+u_long *portp;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which instructs
+.B portmap
+on the host at
+.SM IP
+address
+.I *addr
+to make an
+.SM RPC
+call on your behalf to a procedure on that host.
+The parameter
+.I *portp
+will be modified to the program's port number if the
+procedure
+succeeds. The definitions of other parameters are discussed
+in
+.B callrpc(\|)
+and
+.BR clnt_call(\|) .
+This procedure should be used for a \(lqping\(rq and nothing
+else.
+See also
+.BR clnt_broadcast(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+pmap_set(prognum, versnum, protocol, port)
+u_long prognum, versnum, protocol;
+u_short port;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which establishes a mapping between the triple
+.RI [ prognum , versnum , protocol\fR]
+and
+.I port
+on the machine's
+.B portmap
+service. The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+This routine returns one if it succeeds, zero otherwise.
+Automatically done by
+.BR svc_register(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+pmap_unset(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which destroys all mapping between the triple
+.RI [ prognum , versnum , *\fR]
+and
+.B ports
+on the machine's
+.B portmap
+service. This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+registerrpc(prognum, versnum, procnum, procname, inproc, outproc)
+u_long prognum, versnum, procnum;
+char *(*procname) (\|) ;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Register procedure
+.I procname
+with the
+.SM RPC
+service package. If a request arrives for program
+.IR prognum ,
+version
+.IR versnum ,
+and procedure
+.IR procnum ,
+.I procname
+is called with a pointer to its parameter(s);
+.I progname
+should return a pointer to its static result(s);
+.I inproc
+is used to decode the parameters while
+.I outproc
+is used to encode the results.
+This routine returns zero if the registration succeeded, \-1
+otherwise.
+.IP
+Warning: remote procedures registered in this form
+are accessed using the
+.SM UDP/IP
+transport; see
+.B svcudp_create(\|)
+for restrictions.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+struct rpc_createerr rpc_createerr;
+.fi
+.ft R
+.IP
+A global variable whose value is set by any
+.SM RPC
+client creation routine
+that does not succeed. Use the routine
+.B clnt_pcreateerror(\|)
+to print the reason why.
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+svc_destroy(xprt)
+\s-1SVCXPRT\s0 *
+xprt;
+.fi
+.ft R
+.IP
+A macro that destroys the
+.SM RPC
+service transport handle,
+.IR xprt .
+Destruction usually involves deallocation
+of private data structures, including
+.I xprt
+itself. Use of
+.I xprt
+is undefined after calling this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+fd_set svc_fdset;
+.fi
+.ft R
+.IP
+A global variable reflecting the
+.SM RPC
+service side's
+read file descriptor bit mask; it is suitable as a parameter
+to the
+.B select
+system call. This is only of interest
+if a service implementor does not call
+.BR svc_run(\|) ,
+but rather does his own asynchronous event processing.
+This variable is read-only (do not pass its address to
+.BR select !),
+yet it may change after calls to
+.B svc_getreqset(\|)
+or any creation routines.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+int svc_fds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_fedset(\|) ,
+but limited to 32 descriptors. This
+interface is obsoleted by
+.BR svc_fdset(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_freeargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the arguments to a service procedure
+using
+.BR svc_getargs(\|) .
+This routine returns 1 if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+svc_getargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that decodes the arguments of an
+.SM RPC
+request
+associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+The parameter
+.I in
+is the address where the arguments will be placed;
+.I inproc
+is the
+.SM XDR
+routine used to decode the arguments.
+This routine returns one if decoding succeeds, and zero
+otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+struct sockaddr_in *
+svc_getcaller(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+The approved way of getting the network address of the caller
+of a procedure associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreqset(rdfds)
+fd_set *rdfds;
+.fi
+.ft R
+.IP
+This routine is only of interest if a service implementor
+does not call
+.BR svc_run(\|) ,
+but instead implements custom asynchronous event processing.
+It is called when the
+.B select
+system call has determined that an
+.SM RPC
+request has arrived on some
+.SM RPC
+.B socket(s) ;
+.I rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all sockets associated with the
+value of
+.I rdfds
+have been serviced.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreq(rdfds)
+int rdfds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_getreqset(\|) ,
+but limited to 32 descriptors. This interface is obsoleted by
+.BR svc_getreqset(\|) .
+.br
+.if t .ne 17
+.LP
+.ft B
+.nf
+.sp .5
+svc_register(xprt, prognum, versnum, dispatch, protocol)
+\s-1SVCXPRT\s0 *xprt;
+u_long prognum, versnum;
+void (*dispatch) (\|);
+u_long protocol;
+.fi
+.ft R
+.IP
+Associates
+.I prognum
+and
+.I versnum
+with the service dispatch procedure,
+.IR dispatch .
+If
+.I protocol
+is zero, the service is not registered with the
+.B portmap
+service. If
+.I protocol
+is non-zero, then a mapping of the triple
+.RI [ prognum , versnum , protocol\fR]
+to
+\fB\%xprt\->xp_port\fR
+is established with the local
+.B portmap
+service (generally
+.I protocol
+is zero,
+.B
+.SM IPPROTO_UDP
+or
+.B
+.SM IPPROTO_TCP
+).
+The procedure
+.I dispatch
+has the following form:
+.RS 1i
+.ft B
+.nf
+dispatch(request, xprt)
+struct svc_req *request;
+\s-1SVCXPRT\s0 *xprt;
+.ft R
+.fi
+.RE
+.IP
+The
+.B svc_register(\|)
+routine returns one if it succeeds, and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_run(\|)
+.fi
+.ft R
+.IP
+This routine never returns. It waits for
+.SM RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.B svc_getreq(\|)
+when one arrives. This procedure is usually waiting for a
+.B select(\|)
+system call to return.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_sendreply(xprt, outproc, out)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+Called by an
+.SM RPC
+service's dispatch routine to send the results of a
+remote procedure call. The parameter
+.I xprt
+is the request's associated transport handle;
+.I outproc
+is the
+.SM XDR
+routine which is used to encode the results; and
+.I out
+is the address of the results.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svc_unregister(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+Remove all mapping of the double
+.RI [ prognum , versnum ]
+to dispatch routines, and of the triple
+.RI [ prognum , versnum , *\fR]
+to port number.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_auth(xprt, why)
+\s-1SVCXPRT\s0 *xprt;
+enum auth_stat why;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_decode(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that cannot successfully
+decode its parameters. See also
+.BR svc_getargs(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noproc(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noprog(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired program is not registered with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_progvers(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired version of a program is not registered
+with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_systemerr(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+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.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_weakauth(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient
+authentication parameters. The routine calls
+.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" .
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcraw_create(\|)
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+service transport, to which it returns a pointer. The
+transport
+is really a buffer within the process's address space,
+so the corresponding
+.SM RPC
+client should live in the same
+address space;
+see
+.BR clntraw_create(\|) .
+This routine allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads (such as round trip times), without any kernel
+interference.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svctcp_create(sock, send_buf_size, recv_buf_size)
+int sock;
+u_int send_buf_size, recv_buf_size;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM TCP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.BR \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM TCP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_fd\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails. Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcfd_create(fd, sendsize, recvsize)
+int fd;
+u_int sendsize;
+u_int recvsize;
+.fi
+.ft R
+.IP
+Create a service on top of any open descriptor. Typically,
+this
+descriptor is a connected socket for a stream protocol such
+as
+.SM TCP\s0.
+.I sendsize
+and
+.I recvsize
+indicate sizes for the send and receive buffers. If they are
+zero, a reasonable default is chosen.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcudp_bufcreate(sock, sendsize, recosize)
+int sock;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM UDP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.B \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM UDP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails.
+.IP
+This allows the user to specify the maximum packet size for sending and
+receiving
+.SM UDP\s0-based
+.SM RPC messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_accepted_reply(xdrs, ar)
+\s-1XDR\s0 *xdrs;
+struct accepted_reply *ar;
+.fi
+.ft R
+.IP
+Used for encoding
+.SM RPC
+reply messages. This routine is useful for users who
+wish to generate
+\s-1RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_authunix_parms(xdrs, aupp)
+\s-1XDR\s0 *xdrs;
+struct authunix_parms *aupp;
+.fi
+.ft R
+.IP
+Used for describing
+.SM UNIX
+credentials. This routine is useful for users
+who wish to generate these credentials without using the
+.SM RPC
+authentication package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_callhdr(xdrs, chdr)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *chdr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call header messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_callmsg(xdrs, cmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *cmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque_auth(xdrs, ap)
+\s-1XDR\s0 *xdrs;
+struct opaque_auth *ap;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+authentication information messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmap(xdrs, regs)
+\s-1XDR\s0 *xdrs;
+struct pmap *regs;
+.fi
+.ft R
+.IP
+Used for describing parameters to various
+.B portmap
+procedures, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmaplist(xdrs, rp)
+\s-1XDR\s0 *xdrs;
+struct pmaplist **rp;
+.fi
+.ft R
+.IP
+Used for describing a list of port mappings, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_rejected_reply(xdrs, rr)
+\s-1XDR\s0 *xdrs;
+struct rejected_reply *rr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_replymsg(xdrs, rmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *rmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC
+style messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_register(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+After
+.SM RPC
+service transport handles are created,
+they should register themselves with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_unregister(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Before an
+.SM RPC
+service transport handle is destroyed,
+it should unregister itself with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.SH SEE ALSO
+.\".BR rpc_secure (3),
+.BR xdr (3)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c
new file mode 100644
index 000000000000..07783d67089c
--- /dev/null
+++ b/lib/libc/rpc/rpc_soc.c
@@ -0,0 +1,453 @@
+/* $NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
+
+/*
+ * 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 0
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
+#endif
+#endif
+
+#ifdef PORTMAP
+/*
+ * 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 "reentrant.h"
+#include "namespace.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 "un-namespace.h"
+
+#include "rpc_com.h"
+
+extern mutex_t rpcsoc_lock;
+
+static CLIENT *clnt_com_create __P((struct sockaddr_in *, rpcprog_t, rpcvers_t,
+ int *, u_int, u_int, char *));
+static SVCXPRT *svc_com_create __P((int, u_int, u_int, char *));
+static bool_t rpc_wrap_bcast __P((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;
+ int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+ char *tp;
+{
+ CLIENT *cl;
+ int madefd = FALSE;
+ int 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);
+ 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)_close(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, (char *)(void *)&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");
+}
+
+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)
+ int 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)_close(fd);
+ return (NULL);
+ }
+ port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
+ svc->xp_port = ntohs(port);
+ return (svc);
+}
+
+SVCXPRT *
+svctcp_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return svc_com_create(fd, sendsize, recvsize, "tcp");
+}
+
+SVCXPRT *
+svcudp_bufcreate(fd, sendsz, recvsz)
+ int fd;
+ u_int sendsz, recvsz;
+{
+
+ return svc_com_create(fd, sendsz, recvsz, "udp");
+}
+
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return svc_fd_create(fd, sendsize, recvsize);
+}
+
+
+SVCXPRT *
+svcudp_create(fd)
+ int fd;
+{
+
+ return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
+}
+
+SVCXPRT *
+svcraw_create()
+{
+
+ return svc_raw_create();
+}
+
+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)
+ char *host;
+ int prognum, versnum, procnum;
+ xdrproc_t inproc, outproc;
+ char *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) __P((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
+ */
+static thread_key_t clnt_broadcast_key;
+static resultproc_t clnt_broadcast_result_main;
+
+/*
+ * 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);
+ if (thr_main())
+ clnt_broadcast_result = clnt_broadcast_result_main;
+ else
+ 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 */
+ 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 */
+{
+ extern mutex_t tsd_lock;
+
+ if (thr_main())
+ clnt_broadcast_result_main = eachresult;
+ else {
+ if (clnt_broadcast_key == 0) {
+ mutex_lock(&tsd_lock);
+ if (clnt_broadcast_key == 0)
+ 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");
+}
+
+/*
+ * 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, syncaddr->sa_len, 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 /* PORTMAP */
diff --git a/lib/libc/rpc/rpc_svc_calls.3 b/lib/libc/rpc/rpc_svc_calls.3
new file mode 100644
index 000000000000..06ff75516ec4
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_calls.3
@@ -0,0 +1,263 @@
+.\" @(#)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$
+.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
+.Fd #include <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 "const SVCXPRT *xprt" "const xdrproc_t outproc" "const caddr_t *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
+.Fn rpc_svc_create
+functions, or using
+.Fn xprt_register .
+.Fn svc_exit
+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 a parameter
+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 parameter
+.Fa in
+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
+.Aq Pa 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 a parameter 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 parameter
+.Fa xprt
+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
diff --git a/lib/libc/rpc/rpc_svc_create.3 b/lib/libc/rpc/rpc_svc_create.3
new file mode 100644
index 000000000000..b9788b2e3a70
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_create.3
@@ -0,0 +1,622 @@
+.\" @(#)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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft bool_t
+.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info"
+.Ft int
+.Fn svc_create "const 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 "const void (*dispatch)(const struct svc_reg *, const 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.
+.Fa req
+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.
+.Fa info
+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.
+.Fa info
+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
+.Fn svc_create
+creates server handles for all the transports
+belonging to the class
+.Fa nettype .
+.Fa nettype
+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
+.Fn svc_create
+registers itself with the rpcbind
+service (see
+.Xr rpcbind 8 ) .
+.Fa dispatch
+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.
+.Fa sendsz
+and
+.Fa recvsz
+are parameters 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.
+.Fa sendsz
+and
+.Fa recvsz
+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.
+.Fa fildes
+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
+.Aq Pa 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 parameters
+.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
+.Fn svc_tp_create
+creates a server handle for the network
+specified by
+.Fa netconf ,
+and registers itself with the rpcbind service.
+.Fa dispatch
+is called when there is a remote procedure call
+for the given
+.Fa prognum
+and
+.Fa versnum ;
+this requires calling
+.Fn svc_run .
+.Fn svc_tp_create
+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 parameters
+.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
+.\" @(#)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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft bool_t
+.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info"
+.Ft int
+.Fn svc_create "const 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 "const void (*dispatch)(const struct svc_reg *, const 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.
+.Fa req
+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.
+.Fa info
+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.
+.Fa info
+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
+.Fn svc_create
+creates server handles for all the transports
+belonging to the class
+.Fa nettype .
+.Fa nettype
+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
+.Fn svc_create
+registers itself with the rpcbind
+service (see
+.Xr rpcbind 8 ) .
+.Fa dispatch
+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.
+.Fa sendsz
+and
+.Fa recvsz
+are parameters 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.
+.Fa sendsz
+and
+.Fa recvsz
+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.
+.Fa fildes
+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
+.Aq Pa 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 parameters
+.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
+.Fn svc_tp_create
+creates a server handle for the network
+specified by
+.Fa netconf ,
+and registers itself with the rpcbind service.
+.Fa dispatch
+is called when there is a remote procedure call
+for the given
+.Fa prognum
+and
+.Fa versnum ;
+this requires calling
+.Fn svc_run .
+.Fn svc_tp_create
+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 parameters
+.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
diff --git a/lib/libc/rpc/rpc_svc_err.3 b/lib/libc/rpc/rpc_svc_err.3
new file mode 100644
index 000000000000..3a6e0c9fd4f1
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_err.3
@@ -0,0 +1,95 @@
+.\" @(#)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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft void
+.Fn svcerr_auth "const SVCXPRT1 *xprt" "const enum auth_stat why"
+.Ft void
+.Fn svcerr_decode "const SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_noproc "const SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_noprog "const SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_progvers "const SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers"
+.Ft void
+.Fn svcerr_systemerr "const SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_weakauth "const 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 parameters
+(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.
+.Fa low_vers
+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 parameters.
+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
diff --git a/lib/libc/rpc/rpc_svc_reg.3 b/lib/libc/rpc/rpc_svc_reg.3
new file mode 100644
index 000000000000..2ab6f00e9bca
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_reg.3
@@ -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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft bool_t
+.Fn rpc_reg "const rpcprog_t prognum" "const rpcvers_t versnum" "const rpcproc_t procnum" "const char *(*procname)()" "const xdrproc_t inproc" "const xdrproc_t outproc" "const char *nettype"
+.Ft int
+.Fn svc_reg "const SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "const 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 "const int cred_flavor" "const enum auth_stat (*handler(struct svc_req *, truct rpc_msg *))"
+.Ft void
+.Fn xprt_register "const SVCXPRT *xprt"
+.Ft void
+.Fn xprt_unregister "const 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 parameter(s);
+.Fa procname
+should return a pointer to its static result(s);
+.Fa inproc
+is the XDR function used to decode the parameters 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 parameters,
+.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 rpc_svc_calls 3 ,
+.Xr rpc_svc_create 3 ,
+.Xr rpc_svc_err 3 ,
+.Xr rpcbind 3 ,
+.Xr rpcbind 8
diff --git a/lib/libc/rpc/rpc_xdr.3 b/lib/libc/rpc/rpc_xdr.3
new file mode 100644
index 000000000000..e021a330f8f7
--- /dev/null
+++ b/lib/libc/rpc/rpc_xdr.3
@@ -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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft bool_t
+.Fn xdr_accepted_reply "XDR *xdrs" "const struct accepted_reply *ar"
+.Ft bool_t
+.Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp"
+.Ft void
+.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" "const struct rejected_reply *rr"
+.Ft bool_t
+.Fn xdr_replymsg "XDR *xdrs" "const 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
diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c
new file mode 100644
index 000000000000..2fdc74ff391c
--- /dev/null
+++ b/lib/libc/rpc/rpcb_clnt.c
@@ -0,0 +1,1253 @@
+/* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */
+
+
+#if 0
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro";
+#endif
+#endif
+
+/*
+ * rpcb_clnt.c
+ * interface to rpcbind rpc service.
+ *
+ * Copyright (C) 1988, Sun Microsystems, Inc.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/nettype.h>
+#include <netconfig.h>
+#ifdef PORTMAP
+#include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
+#include <rpc/pmap_prot.h>
+#endif /* PORTMAP */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+static struct timeval tottimeout = { 60, 0 };
+static const struct timeval rmttimeout = { 3, 0 };
+
+extern bool_t xdr_wrapstring __P((XDR *, char **));
+
+static const char nullstring[] = "\000";
+
+#define CACHESIZE 6
+
+struct address_cache {
+ char *ac_host;
+ char *ac_netid;
+ char *ac_uaddr;
+ struct netbuf *ac_taddr;
+ struct address_cache *ac_next;
+};
+
+static struct address_cache *front;
+static int cachesize;
+
+#define CLCR_GET_RPCB_TIMEOUT 1
+#define CLCR_SET_RPCB_TIMEOUT 2
+
+
+extern int __rpc_lowvers;
+
+static struct address_cache *check_cache __P((const char *, const char *));
+static void delete_cache __P((struct netbuf *));
+static void add_cache __P((const char *, const char *, struct netbuf *,
+ char *));
+static CLIENT *getclnthandle __P((const char *, const struct netconfig *,
+ char **));
+static CLIENT *local_rpcb __P((void));
+static struct netbuf *got_entry __P((rpcb_entry_list_ptr,
+ const struct netconfig *));
+
+/*
+ * This routine adjusts the timeout used for calls to the remote rpcbind.
+ * Also, this routine can be used to set the use of portmapper version 2
+ * only when doing rpc_broadcasts
+ * These are private routines that may not be provided in future releases.
+ */
+bool_t
+__rpc_control(request, info)
+ int request;
+ void *info;
+{
+ switch (request) {
+ case CLCR_GET_RPCB_TIMEOUT:
+ *(struct timeval *)info = tottimeout;
+ break;
+ case CLCR_SET_RPCB_TIMEOUT:
+ tottimeout = *(struct timeval *)info;
+ break;
+ case CLCR_SET_LOWVERS:
+ __rpc_lowvers = *(int *)info;
+ break;
+ case CLCR_GET_LOWVERS:
+ *(int *)info = __rpc_lowvers;
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * It might seem that a reader/writer lock would be more reasonable here.
+ * However because getclnthandle(), the only user of the cache functions,
+ * may do a delete_cache() operation if a check_cache() fails to return an
+ * address useful to clnt_tli_create(), we may as well use a mutex.
+ */
+/*
+ * As it turns out, if the cache lock is *not* a reader/writer lock, we will
+ * block all clnt_create's if we are trying to connect to a host that's down,
+ * since the lock will be held all during that time.
+ */
+extern rwlock_t rpcbaddr_cache_lock;
+
+/*
+ * The routines check_cache(), add_cache(), delete_cache() manage the
+ * cache of rpcbind addresses for (host, netid).
+ */
+
+static struct address_cache *
+check_cache(host, netid)
+ const char *host, *netid;
+{
+ struct address_cache *cptr;
+
+ /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+
+ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+ if (!strcmp(cptr->ac_host, host) &&
+ !strcmp(cptr->ac_netid, netid)) {
+#ifdef ND_DEBUG
+ fprintf(stderr, "Found cache entry for %s: %s\n",
+ host, netid);
+#endif
+ return (cptr);
+ }
+ }
+ return ((struct address_cache *) NULL);
+}
+
+static void
+delete_cache(addr)
+ struct netbuf *addr;
+{
+ struct address_cache *cptr, *prevptr = NULL;
+
+ /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+ if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
+ free(cptr->ac_host);
+ free(cptr->ac_netid);
+ free(cptr->ac_taddr->buf);
+ free(cptr->ac_taddr);
+ if (cptr->ac_uaddr)
+ free(cptr->ac_uaddr);
+ if (prevptr)
+ prevptr->ac_next = cptr->ac_next;
+ else
+ front = cptr->ac_next;
+ free(cptr);
+ cachesize--;
+ break;
+ }
+ prevptr = cptr;
+ }
+}
+
+static void
+add_cache(host, netid, taddr, uaddr)
+ const char *host, *netid;
+ char *uaddr;
+ struct netbuf *taddr;
+{
+ struct address_cache *ad_cache, *cptr, *prevptr;
+
+ ad_cache = (struct address_cache *)
+ malloc(sizeof (struct address_cache));
+ if (!ad_cache) {
+ return;
+ }
+ ad_cache->ac_host = strdup(host);
+ ad_cache->ac_netid = strdup(netid);
+ ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
+ ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
+ (uaddr && !ad_cache->ac_uaddr)) {
+ return;
+ }
+ ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
+ ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
+ if (ad_cache->ac_taddr->buf == NULL) {
+ return;
+ }
+ memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
+#ifdef ND_DEBUG
+ fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
+#endif
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
+
+ rwlock_wrlock(&rpcbaddr_cache_lock);
+ if (cachesize < CACHESIZE) {
+ ad_cache->ac_next = front;
+ front = ad_cache;
+ cachesize++;
+ } else {
+ /* Free the last entry */
+ cptr = front;
+ prevptr = NULL;
+ while (cptr->ac_next) {
+ prevptr = cptr;
+ cptr = cptr->ac_next;
+ }
+
+#ifdef ND_DEBUG
+ fprintf(stderr, "Deleted from cache: %s : %s\n",
+ cptr->ac_host, cptr->ac_netid);
+#endif
+ free(cptr->ac_host);
+ free(cptr->ac_netid);
+ free(cptr->ac_taddr->buf);
+ free(cptr->ac_taddr);
+ if (cptr->ac_uaddr)
+ free(cptr->ac_uaddr);
+
+ if (prevptr) {
+ prevptr->ac_next = NULL;
+ ad_cache->ac_next = front;
+ front = ad_cache;
+ } else {
+ front = ad_cache;
+ ad_cache->ac_next = NULL;
+ }
+ free(cptr);
+ }
+ rwlock_unlock(&rpcbaddr_cache_lock);
+}
+
+/*
+ * This routine will return a client handle that is connected to the
+ * rpcbind. Returns NULL on error and free's everything.
+ */
+static CLIENT *
+getclnthandle(host, nconf, targaddr)
+ const char *host;
+ const struct netconfig *nconf;
+ char **targaddr;
+{
+ CLIENT *client;
+ struct netbuf *addr, taddr;
+ struct netbuf addr_to_delete;
+ struct __rpc_sockinfo si;
+ struct addrinfo hints, *res, *tres;
+ struct address_cache *ad_cache;
+ char *tmpaddr;
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
+
+ /* Get the address of the rpcbind. Check cache first */
+ addr_to_delete.len = 0;
+ rwlock_rdlock(&rpcbaddr_cache_lock);
+ ad_cache = check_cache(host, nconf->nc_netid);
+ if (ad_cache != NULL) {
+ addr = ad_cache->ac_taddr;
+ client = clnt_tli_create(RPC_ANYFD, nconf, addr,
+ (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+ if (client != NULL) {
+ if (targaddr)
+ *targaddr = ad_cache->ac_uaddr;
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ return (client);
+ }
+ addr_to_delete.len = addr->len;
+ addr_to_delete.buf = (char *)malloc(addr->len);
+ if (addr_to_delete.buf == NULL) {
+ addr_to_delete.len = 0;
+ } else {
+ memcpy(addr_to_delete.buf, addr->buf, addr->len);
+ }
+ }
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ if (addr_to_delete.len != 0) {
+ /*
+ * Assume this may be due to cache data being
+ * outdated
+ */
+ rwlock_wrlock(&rpcbaddr_cache_lock);
+ delete_cache(&addr_to_delete);
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ free(addr_to_delete.buf);
+ }
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return NULL;
+ }
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = si.si_af;
+ hints.ai_socktype = si.si_socktype;
+ hints.ai_protocol = si.si_proto;
+
+#ifdef CLNT_DEBUG
+ printf("trying netid %s family %d proto %d socktype %d\n",
+ nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
+#endif
+
+ if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ return NULL;
+ }
+
+ for (tres = res; tres != NULL; tres = tres->ai_next) {
+ taddr.buf = tres->ai_addr;
+ taddr.len = taddr.maxlen = tres->ai_addrlen;
+
+#ifdef ND_DEBUG
+ {
+ char *ua;
+
+ ua = taddr2uaddr(nconf, &taddr);
+ fprintf(stderr, "Got it [%s]\n", ua);
+ free(ua);
+ }
+#endif
+
+#ifdef ND_DEBUG
+ {
+ int i;
+
+ fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
+ taddr.len, taddr.maxlen);
+ fprintf(stderr, "\tAddress is ");
+ for (i = 0; i < taddr.len; i++)
+ fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
+ fprintf(stderr, "\n");
+ }
+#endif
+ client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
+ (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+#ifdef ND_DEBUG
+ if (! client) {
+ clnt_pcreateerror("rpcbind clnt interface");
+ }
+#endif
+
+ if (client) {
+ tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
+ add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
+ if (targaddr)
+ *targaddr = tmpaddr;
+ break;
+ }
+ }
+ freeaddrinfo(res);
+ return (client);
+}
+
+/* XXX */
+#define IN4_LOCALHOST_STRING "127.0.0.1"
+#define IN6_LOCALHOST_STRING "::1"
+
+/*
+ * This routine will return a client handle that is connected to the local
+ * rpcbind. Returns NULL on error and free's everything.
+ */
+static CLIENT *
+local_rpcb()
+{
+ CLIENT *client;
+ static struct netconfig *loopnconf;
+ static char *hostname;
+ extern mutex_t loopnconf_lock;
+ int sock;
+ size_t tsize;
+ struct netbuf nbuf;
+ struct sockaddr_un sun;
+
+ /*
+ * Try connecting to the local rpcbind through a local socket
+ * first. If this doesn't work, try all transports defined in
+ * the netconfig file.
+ */
+ memset(&sun, 0, sizeof sun);
+ sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ goto try_nconf;
+ sun.sun_family = AF_LOCAL;
+ strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+ nbuf.len = sun.sun_len = SUN_LEN(&sun);
+ nbuf.maxlen = sizeof (struct sockaddr_un);
+ nbuf.buf = &sun;
+
+ tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
+ client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
+ (rpcvers_t)RPCBVERS, tsize, tsize);
+
+ if (client != NULL)
+ return client;
+
+try_nconf:
+
+/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
+ mutex_lock(&loopnconf_lock);
+ if (loopnconf == NULL) {
+ struct netconfig *nconf, *tmpnconf = NULL;
+ void *nc_handle;
+ int fd;
+
+ nc_handle = setnetconfig();
+ if (nc_handle == NULL) {
+ /* fails to open netconfig file */
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ mutex_unlock(&loopnconf_lock);
+ return (NULL);
+ }
+ while ((nconf = getnetconfig(nc_handle)) != NULL) {
+#ifdef INET6
+ if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
+#else
+ if ((
+#endif
+ strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
+ (nconf->nc_semantics == NC_TPI_COTS ||
+ nconf->nc_semantics == NC_TPI_COTS_ORD)) {
+ fd = __rpc_nconf2fd(nconf);
+ /*
+ * Can't create a socket, assume that
+ * this family isn't configured in the kernel.
+ */
+ if (fd < 0)
+ continue;
+ _close(fd);
+ tmpnconf = nconf;
+ if (!strcmp(nconf->nc_protofmly, NC_INET))
+ hostname = IN4_LOCALHOST_STRING;
+ else
+ hostname = IN6_LOCALHOST_STRING;
+ }
+ }
+ if (tmpnconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ mutex_unlock(&loopnconf_lock);
+ return (NULL);
+ }
+ loopnconf = getnetconfigent(tmpnconf->nc_netid);
+ /* loopnconf is never freed */
+ endnetconfig(nc_handle);
+ }
+ mutex_unlock(&loopnconf_lock);
+ client = getclnthandle(hostname, loopnconf, NULL);
+ return (client);
+}
+
+/*
+ * Set a mapping between program, version and address.
+ * Calls the rpcbind service to do the mapping.
+ */
+bool_t
+rpcb_set(program, version, nconf, address)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf; /* Network structure of transport */
+ const struct netbuf *address; /* Services netconfig address */
+{
+ CLIENT *client;
+ bool_t rslt = FALSE;
+ RPCB parms;
+ char uidbuf[32];
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (FALSE);
+ }
+ if (address == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (FALSE);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (FALSE);
+ }
+
+ /* convert to universal */
+ /*LINTED const castaway*/
+ parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
+ (struct netbuf *)address);
+ if (!parms.r_addr) {
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ return (FALSE); /* no universal address */
+ }
+ parms.r_prog = program;
+ parms.r_vers = version;
+ parms.r_netid = nconf->nc_netid;
+ /*
+ * Though uid is not being used directly, we still send it for
+ * completeness. For non-unix platforms, perhaps some other
+ * string or an empty string can be sent.
+ */
+ (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+ parms.r_owner = uidbuf;
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
+ (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+ (char *)(void *)&rslt, tottimeout);
+
+ CLNT_DESTROY(client);
+ free(parms.r_addr);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program, version and netbuf address.
+ * Calls the rpcbind service to do the un-mapping.
+ * If netbuf is NULL, unset for all the transports, otherwise unset
+ * only for the given transport.
+ */
+bool_t
+rpcb_unset(program, version, nconf)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+{
+ CLIENT *client;
+ bool_t rslt = FALSE;
+ RPCB parms;
+ char uidbuf[32];
+
+ client = local_rpcb();
+ if (! client) {
+ return (FALSE);
+ }
+
+ parms.r_prog = program;
+ parms.r_vers = version;
+ if (nconf)
+ parms.r_netid = nconf->nc_netid;
+ else {
+ /*LINTED const castaway*/
+ parms.r_netid = (char *) &nullstring[0]; /* unsets all */
+ }
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0];
+ (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+ parms.r_owner = uidbuf;
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
+ (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+ (char *)(void *)&rslt, tottimeout);
+
+ CLNT_DESTROY(client);
+ return (rslt);
+}
+
+/*
+ * From the merged list, find the appropriate entry
+ */
+static struct netbuf *
+got_entry(relp, nconf)
+ rpcb_entry_list_ptr relp;
+ const struct netconfig *nconf;
+{
+ struct netbuf *na = NULL;
+ rpcb_entry_list_ptr sp;
+ rpcb_entry *rmap;
+
+ for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
+ rmap = &sp->rpcb_entry_map;
+ if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
+ (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
+ (nconf->nc_semantics == rmap->r_nc_semantics) &&
+ (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != NULL)) {
+ na = uaddr2taddr(nconf, rmap->r_maddr);
+#ifdef ND_DEBUG
+ fprintf(stderr, "\tRemote address is [%s].\n",
+ rmap->r_maddr);
+ if (!na)
+ fprintf(stderr,
+ "\tCouldn't resolve remote address!\n");
+#endif
+ break;
+ }
+ }
+ return (na);
+}
+
+/*
+ * An internal function which optimizes rpcb_getaddr function. It also
+ * returns the client handle that it uses to contact the remote rpcbind.
+ *
+ * The algorithm used: If the transports is TCP or UDP, it first tries
+ * version 2 (portmap), 4 and then 3 (svr4). This order should be
+ * changed in the next OS release to 4, 2 and 3. We are assuming that by
+ * that time, version 4 would be available on many machines on the network.
+ * With this algorithm, we get performance as well as a plan for
+ * obsoleting version 2.
+ *
+ * For all other transports, the algorithm remains as 4 and then 3.
+ *
+ * XXX: Due to some problems with t_connect(), we do not reuse the same client
+ * handle for COTS cases and hence in these cases we do not return the
+ * client handle. This code will change if t_connect() ever
+ * starts working properly. Also look under clnt_vc.c.
+ */
+struct netbuf *
+__rpcb_findaddr(program, version, nconf, host, clpp)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+ const char *host;
+ CLIENT **clpp;
+{
+ CLIENT *client = NULL;
+ RPCB parms;
+ enum clnt_stat clnt_st;
+ char *ua = NULL;
+ rpcvers_t vers;
+ struct netbuf *address = NULL;
+ rpcvers_t start_vers = RPCBVERS4;
+ struct netbuf servaddr;
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+
+ parms.r_addr = NULL;
+
+#ifdef PORTMAP
+ /* Try version 2 for TCP or UDP */
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
+ u_short port = 0;
+ struct netbuf remote;
+ rpcvers_t pmapvers = 2;
+ struct pmap pmapparms;
+
+ /*
+ * Try UDP only - there are some portmappers out
+ * there that use UDP only.
+ */
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ struct netconfig *newnconf;
+
+ if ((newnconf = getnetconfigent("udp")) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ client = getclnthandle(host, newnconf, &parms.r_addr);
+ freenetconfigent(newnconf);
+ } else {
+ client = getclnthandle(host, nconf, &parms.r_addr);
+ }
+ if (client == NULL) {
+ return (NULL);
+ }
+
+ /* Set the version */
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&pmapvers);
+ pmapparms.pm_prog = program;
+ pmapparms.pm_vers = version;
+ pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
+ IPPROTO_UDP : IPPROTO_TCP;
+ pmapparms.pm_port = 0; /* not needed */
+ clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
+ (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
+ (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
+ tottimeout);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL))
+ goto try_rpcbind; /* Try different versions */
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ } else if (port == 0) {
+ address = NULL;
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ goto error;
+ }
+ port = htons(port);
+ CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)(void *)&remote);
+ if (((address = (struct netbuf *)
+ malloc(sizeof (struct netbuf))) == NULL) ||
+ ((address->buf = (char *)
+ malloc(remote.len)) == NULL)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ if (address) {
+ free(address);
+ address = NULL;
+ }
+ goto error;
+ }
+ memcpy(address->buf, remote.buf, remote.len);
+ memcpy(&((char *)address->buf)[sizeof (short)],
+ (char *)(void *)&port, sizeof (short));
+ address->len = address->maxlen = remote.len;
+ goto done;
+ }
+#endif /* PORTMAP */
+
+try_rpcbind:
+ /*
+ * Now we try version 4 and then 3.
+ * We also send the remote system the address we used to
+ * contact it in case it can help to connect back with us
+ */
+ parms.r_prog = program;
+ parms.r_vers = version;
+ /*LINTED const castaway*/
+ parms.r_owner = (char *) &nullstring[0]; /* not needed; */
+ /* just for xdring */
+ parms.r_netid = nconf->nc_netid; /* not really needed */
+
+ /*
+ * If a COTS transport is being used, try getting address via CLTS
+ * transport. This works only with version 4.
+ * NOTE: This is being done for all transports EXCEPT LOOPBACK
+ * because with loopback the cost to go to a COTS is same as
+ * the cost to go through CLTS, plus you get the advantage of
+ * finding out immediately if the local rpcbind process is dead.
+ */
+#if 1
+ if ((nconf->nc_semantics == NC_TPI_COTS_ORD ||
+ nconf->nc_semantics == NC_TPI_COTS) &&
+ (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0)) {
+#else
+ if (client != NULL) {
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+ if (nconf->nc_semantics == NC_TPI_CLTS) {
+#endif
+ void *handle;
+ struct netconfig *nconf_clts;
+ rpcb_entry_list_ptr relp = NULL;
+
+ if (client == NULL) {
+ /* This did not go through the above PORTMAP/TCP code */
+#if 1
+ if ((handle = __rpc_setconf("datagram_v")) != NULL) {
+#else
+ if ((handle = __rpc_setconf("circuit_v")) != NULL) {
+#endif
+ while ((nconf_clts = __rpc_getconf(handle))
+ != NULL) {
+ if (strcmp(nconf_clts->nc_protofmly,
+ nconf->nc_protofmly) != 0) {
+ continue;
+ }
+ client = getclnthandle(host, nconf_clts,
+ &parms.r_addr);
+ break;
+ }
+ __rpc_endconf(handle);
+ }
+ if (client == NULL)
+ goto regular_rpcbind; /* Go the regular way */
+ } else {
+ /* This is a UDP PORTMAP handle. Change to version 4 */
+ vers = RPCBVERS4;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ }
+ /*
+ * We also send the remote system the address we used to
+ * contact it in case it can help it connect back with us
+ */
+ if (parms.r_addr == NULL) {
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
+ }
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST,
+ (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
+ (xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp, tottimeout);
+ if (clnt_st == RPC_SUCCESS) {
+ if ((address = got_entry(relp, nconf)) != NULL) {
+ xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp);
+ goto done;
+ }
+ /* Entry not found for this transport */
+ xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp);
+ /*
+ * XXX: should have perhaps returned with error but
+ * since the remote machine might not always be able
+ * to send the address on all transports, we try the
+ * regular way with regular_rpcbind
+ */
+ goto regular_rpcbind;
+ } else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ start_vers = RPCBVERS; /* Try version 3 now */
+ goto regular_rpcbind; /* Try different versions */
+ } else {
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ }
+ }
+
+regular_rpcbind:
+
+ /* Now the same transport is to be used to get the address */
+#if 1
+ if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
+ (nconf->nc_semantics == NC_TPI_COTS))) {
+#else
+ if (client && nconf->nc_semantics == NC_TPI_CLTS) {
+#endif
+ /* A CLTS type of client - destroy it */
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+
+ if (client == NULL) {
+ client = getclnthandle(host, nconf, &parms.r_addr);
+ if (client == NULL) {
+ goto error;
+ }
+ }
+ if (parms.r_addr == NULL) {
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0];
+ }
+
+ /* First try from start_vers and then version 3 (RPCBVERS) */
+ for (vers = start_vers; vers >= RPCBVERS; vers--) {
+ /* Set the version */
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
+ (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua,
+ tottimeout);
+ if (clnt_st == RPC_SUCCESS) {
+ if ((ua == NULL) || (ua[0] == NULL)) {
+ /* address unknown */
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ goto error;
+ }
+ address = uaddr2taddr(nconf, ua);
+#ifdef ND_DEBUG
+ fprintf(stderr, "\tRemote address is [%s]\n", ua);
+ if (!address)
+ fprintf(stderr,
+ "\tCouldn't resolve remote address!\n");
+#endif
+ xdr_free((xdrproc_t)xdr_wrapstring,
+ (char *)(void *)&ua);
+
+ if (! address) {
+ /* We don't know about your universal address */
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ goto error;
+ }
+ CLNT_CONTROL(client, CLGET_SVC_ADDR,
+ (char *)(void *)&servaddr);
+ __rpc_fixup_addr(address, &servaddr);
+ goto done;
+ } else if (clnt_st == RPC_PROGVERSMISMATCH) {
+ struct rpc_err rpcerr;
+
+ clnt_geterr(client, &rpcerr);
+ if (rpcerr.re_vers.low > RPCBVERS4)
+ goto error; /* a new version, can't handle */
+ } else if (clnt_st != RPC_PROGUNAVAIL) {
+ /* Cant handle this error */
+ rpc_createerr.cf_stat = clnt_st;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ }
+ }
+
+ if ((address == NULL) || (address->len == 0)) {
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ }
+
+error:
+ if (client) {
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+done:
+ if (nconf->nc_semantics != NC_TPI_CLTS) {
+ /* This client is the connectionless one */
+ if (client) {
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+ }
+ if (clpp) {
+ *clpp = client;
+ } else if (client) {
+ CLNT_DESTROY(client);
+ }
+ return (address);
+}
+
+
+/*
+ * Find the mapped address for program, version.
+ * Calls the rpcbind service remotely to do the lookup.
+ * Uses the transport specified in nconf.
+ * Returns FALSE (0) if no map exists, else returns 1.
+ *
+ * Assuming that the address is all properly allocated
+ */
+int
+rpcb_getaddr(program, version, nconf, address, host)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+ struct netbuf *address;
+ const char *host;
+{
+ struct netbuf *na;
+
+ if ((na = __rpcb_findaddr(program, version, nconf,
+ host, (CLIENT **) NULL)) == NULL)
+ return (FALSE);
+
+ if (na->len > address->maxlen) {
+ /* Too long address */
+ free(na->buf);
+ free(na);
+ rpc_createerr.cf_stat = RPC_FAILED;
+ return (FALSE);
+ }
+ memcpy(address->buf, na->buf, (size_t)na->len);
+ address->len = na->len;
+ free(na->buf);
+ free(na);
+ return (TRUE);
+}
+
+/*
+ * Get a copy of the current maps.
+ * Calls the rpcbind service remotely to get the maps.
+ *
+ * It returns only a list of the services
+ * It returns NULL on failure.
+ */
+rpcblist *
+rpcb_getmaps(nconf, host)
+ const struct netconfig *nconf;
+ const char *host;
+{
+ rpcblist_ptr head = NULL;
+ CLIENT *client;
+ enum clnt_stat clnt_st;
+ rpcvers_t vers = 0;
+
+ client = getclnthandle(host, nconf, NULL);
+ if (client == NULL) {
+ return (head);
+ }
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+ (char *)(void *)&head, tottimeout);
+ if (clnt_st == RPC_SUCCESS)
+ goto done;
+
+ if ((clnt_st != RPC_PROGVERSMISMATCH) &&
+ (clnt_st != RPC_PROGUNAVAIL)) {
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto done;
+ }
+
+ /* fall back to earlier version */
+ CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+ if (vers == RPCBVERS4) {
+ vers = RPCBVERS;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+ (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
+ goto done;
+ }
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+
+done:
+ CLNT_DESTROY(client);
+ return (head);
+}
+
+/*
+ * rpcbinder remote-call-service interface.
+ * This routine is used to call the rpcbind remote call service
+ * which will look up a service program in the address 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
+rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
+ xdrres, resp, tout, addr_ptr)
+ const struct netconfig *nconf; /* Netconfig structure */
+ const char *host; /* Remote host name */
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc; /* Remote proc identifiers */
+ xdrproc_t xdrargs, xdrres; /* XDR routines */
+ caddr_t argsp, resp; /* Argument and Result */
+ struct timeval tout; /* Timeout value for this call */
+ const struct netbuf *addr_ptr; /* Preallocated netbuf address */
+{
+ CLIENT *client;
+ enum clnt_stat stat;
+ struct r_rpcb_rmtcallargs a;
+ struct r_rpcb_rmtcallres r;
+ rpcvers_t rpcb_vers;
+
+
+ client = getclnthandle(host, nconf, NULL);
+ if (client == NULL) {
+ return (RPC_FAILED);
+ }
+ /*LINTED const castaway*/
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.args.args_val = argsp;
+ a.xdr_args = xdrargs;
+ r.addr = NULL;
+ r.results.results_val = resp;
+ r.xdr_res = xdrres;
+
+ for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
+ stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
+ (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
+ (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
+ if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
+ struct netbuf *na;
+ /*LINTED const castaway*/
+ na = uaddr2taddr((struct netconfig *) nconf, r.addr);
+ if (!na) {
+ stat = RPC_N2AXLATEFAILURE;
+ /*LINTED const castaway*/
+ ((struct netbuf *) addr_ptr)->len = 0;
+ goto error;
+ }
+ if (na->len > addr_ptr->maxlen) {
+ /* Too long address */
+ stat = RPC_FAILED; /* XXX A better error no */
+ free(na->buf);
+ free(na);
+ /*LINTED const castaway*/
+ ((struct netbuf *) addr_ptr)->len = 0;
+ goto error;
+ }
+ memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
+ /*LINTED const castaway*/
+ ((struct netbuf *)addr_ptr)->len = na->len;
+ free(na->buf);
+ free(na);
+ break;
+ } else if ((stat != RPC_PROGVERSMISMATCH) &&
+ (stat != RPC_PROGUNAVAIL)) {
+ goto error;
+ }
+ }
+error:
+ CLNT_DESTROY(client);
+ if (r.addr)
+ xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
+ return (stat);
+}
+
+/*
+ * Gets the time on the remote host.
+ * Returns 1 if succeeds else 0.
+ */
+bool_t
+rpcb_gettime(host, timep)
+ const char *host;
+ time_t *timep;
+{
+ CLIENT *client = NULL;
+ void *handle;
+ struct netconfig *nconf;
+ rpcvers_t vers;
+ enum clnt_stat st;
+
+
+ if ((host == NULL) || (host[0] == NULL)) {
+ time(timep);
+ return (TRUE);
+ }
+
+ if ((handle = __rpc_setconf("netpath")) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (FALSE);
+ }
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ while (client == NULL) {
+ if ((nconf = __rpc_getconf(handle)) == NULL) {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+ client = getclnthandle(host, nconf, NULL);
+ if (client)
+ break;
+ }
+ __rpc_endconf(handle);
+ if (client == (CLIENT *) NULL) {
+ return (FALSE);
+ }
+
+ st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
+
+ if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
+ CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+ if (vers == RPCBVERS4) {
+ /* fall back to earlier version */
+ vers = RPCBVERS;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_int, (char *)(void *)timep,
+ tottimeout);
+ }
+ }
+ CLNT_DESTROY(client);
+ return (st == RPC_SUCCESS? TRUE: FALSE);
+}
+
+/*
+ * Converts taddr to universal address. This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+char *
+rpcb_taddr2uaddr(nconf, taddr)
+ struct netconfig *nconf;
+ struct netbuf *taddr;
+{
+ CLIENT *client;
+ char *uaddr = NULL;
+
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ if (taddr == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (NULL);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (NULL);
+ }
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
+ (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
+ CLNT_DESTROY(client);
+ return (uaddr);
+}
+
+/*
+ * Converts universal address to netbuf. This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+struct netbuf *
+rpcb_uaddr2taddr(nconf, uaddr)
+ struct netconfig *nconf;
+ char *uaddr;
+{
+ CLIENT *client;
+ struct netbuf *taddr;
+
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ if (uaddr == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (NULL);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (NULL);
+ }
+
+ taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
+ if (taddr == NULL) {
+ CLNT_DESTROY(client);
+ return (NULL);
+ }
+ if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
+ (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+ tottimeout) != RPC_SUCCESS) {
+ free(taddr);
+ taddr = NULL;
+ }
+ CLNT_DESTROY(client);
+ return (taddr);
+}
diff --git a/lib/libc/rpc/rpcb_prot.c b/lib/libc/rpc/rpcb_prot.c
new file mode 100644
index 000000000000..aa4651087694
--- /dev/null
+++ b/lib/libc/rpc/rpcb_prot.c
@@ -0,0 +1,329 @@
+/* $NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)rpcb_prot.c 1.13 94/04/24 SMI" */
+
+#if 0
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
+#endif
+#endif
+
+/*
+ * rpcb_prot.c
+ * XDR routines for the rpcbinder version 3.
+ *
+ * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpcb_prot.h>
+#include "un-namespace.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;
+
+ 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;
+
+ 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);
+}
diff --git a/lib/libc/rpc/rpcb_st_xdr.c b/lib/libc/rpc/rpcb_st_xdr.c
new file mode 100644
index 000000000000..c094e9974e62
--- /dev/null
+++ b/lib/libc/rpc/rpcb_st_xdr.c
@@ -0,0 +1,265 @@
+/* $NetBSD: rpcb_st_xdr.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * 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 "namespace.h"
+#include <rpc/rpc.h>
+#include "un-namespace.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);
+ }
+ 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);
+}
diff --git a/lib/libc/rpc/rpcbind.3 b/lib/libc/rpc/rpcbind.3
new file mode 100644
index 000000000000..309269648607
--- /dev/null
+++ b/lib/libc/rpc/rpcbind.3
@@ -0,0 +1,189 @@
+.\" @(#)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$
+.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
+.Fd #include <rpc/rpc.h>
+.Ft "struct 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" "caddr_t out" "const struct timeval tout, 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 .
+.Fa svcaddr
+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.
+.Fn rpcb_gettime
+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 parameter
+.Fa svcaddr
+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 parameters).
+.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
diff --git a/lib/libc/rpc/rpcdname.c b/lib/libc/rpc/rpcdname.c
index f28b4fda9b8a..03d1b8542c54 100644
--- a/lib/libc/rpc/rpcdname.c
+++ b/lib/libc/rpc/rpcdname.c
@@ -30,15 +30,18 @@
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro";
#endif
+/* $FreeBSD$ */
/*
* rpcdname.c
* Gets the default domain name
*/
+#include "namespace.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include "un-namespace.h"
static char *default_domain = 0;
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c
index 94d6057e6004..6e57245a4dd5 100644
--- a/lib/libc/rpc/svc.c
+++ b/lib/libc/rpc/svc.c
@@ -1,3 +1,5 @@
+/* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -43,17 +45,30 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
-#include <string.h>
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <assert.h>
+#include <errno.h>
#include <stdlib.h>
+#include <string.h>
+
#include <rpc/rpc.h>
+#ifdef PORTMAP
#include <rpc/pmap_clnt.h>
+#endif /* PORTMAP */
+#include "un-namespace.h"
+
+#include "rpc_com.h"
static SVCXPRT **xports;
-static int xportssize;
-#define NULL_SVC ((struct svc_callout *)0)
#define RQCRED_SIZE 400 /* this size is excessive */
+#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */
+#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET)
+
#define max(a, b) (a > b ? a : b)
/*
@@ -64,15 +79,17 @@ static int xportssize;
*/
static struct svc_callout {
struct svc_callout *sc_next;
- u_long sc_prog;
- u_long sc_vers;
- void (*sc_dispatch)();
+ rpcprog_t sc_prog;
+ rpcvers_t sc_vers;
+ char *sc_netid;
+ void (*sc_dispatch) __P((struct svc_req *, SVCXPRT *));
} *svc_head;
-static struct svc_callout *svc_find();
+extern rwlock_t svc_lock;
+extern rwlock_t svc_fd_lock;
-int __svc_fdsetsize = 0;
-fd_set *__svc_fdset = NULL;
+static struct svc_callout *svc_find __P((rpcprog_t, rpcvers_t,
+ struct svc_callout **, char *));
/* *************** SVCXPRT related stuff **************** */
@@ -83,75 +100,161 @@ void
xprt_register(xprt)
SVCXPRT *xprt;
{
- register int sock = xprt->xp_sock;
-
- if (sock + 1 > __svc_fdsetsize) {
- int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
- fd_set *fds;
-
- fds = (fd_set *)malloc(bytes);
- memset(fds, 0, bytes);
- if (__svc_fdset) {
- memcpy(fds, __svc_fdset, howmany(__svc_fdsetsize,
- NFDBITS) * sizeof(fd_mask));
- free(__svc_fdset);
- }
- __svc_fdset = fds;
- __svc_fdsetsize = howmany(sock+1, NFDBITS) * NFDBITS;
- }
+ int sock;
+
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
- if (sock < FD_SETSIZE)
+ rwlock_wrlock(&svc_fd_lock);
+ if (xports == NULL) {
+ xports = (SVCXPRT **)
+ mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+ if (xports == NULL)
+ return;
+ memset(xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *));
+ }
+ if (sock < FD_SETSIZE) {
+ xports[sock] = xprt;
FD_SET(sock, &svc_fdset);
- FD_SET(sock, __svc_fdset);
-
- if (xports == NULL || sock + 1 > xportssize) {
- SVCXPRT **xp;
- int size = FD_SETSIZE;
-
- if (sock + 1 > size)
- size = sock + 1;
- xp = (SVCXPRT **)mem_alloc(size * sizeof(SVCXPRT *));
- memset(xp, 0, size * sizeof(SVCXPRT *));
- if (xports) {
- memcpy(xp, xports, xportssize * sizeof(SVCXPRT *));
- free(xports);
- }
- xportssize = size;
- xports = xp;
+ svc_maxfd = max(svc_maxfd, sock);
}
- xports[sock] = xprt;
- svc_maxfd = max(svc_maxfd, sock);
+ rwlock_unlock(&svc_fd_lock);
}
/*
* De-activate a transport handle.
*/
void
-xprt_unregister(xprt)
+xprt_unregister(xprt)
SVCXPRT *xprt;
{
- register int sock = xprt->xp_sock;
-
- if (xports[sock] == xprt) {
- xports[sock] = (SVCXPRT *)0;
- if (sock < FD_SETSIZE)
- FD_CLR(sock, &svc_fdset);
- FD_CLR(sock, __svc_fdset);
- if (sock == svc_maxfd) {
- for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--)
+ int sock;
+
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
+
+ rwlock_wrlock(&svc_fd_lock);
+ if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) {
+ xports[sock] = NULL;
+ FD_CLR(sock, &svc_fdset);
+ if (sock >= svc_maxfd) {
+ for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--)
if (xports[svc_maxfd])
break;
}
- /*
- * XXX could use svc_maxfd as a hint to
- * decrease the size of __svc_fdset
- */
}
+ rwlock_unlock(&svc_fd_lock);
}
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_reg(xprt, prog, vers, dispatch, nconf)
+ SVCXPRT *xprt;
+ const rpcprog_t prog;
+ const rpcvers_t vers;
+ void (*dispatch) __P((struct svc_req *, SVCXPRT *));
+ const struct netconfig *nconf;
+{
+ bool_t dummy;
+ struct svc_callout *prev;
+ struct svc_callout *s;
+ struct netconfig *tnconf;
+ char *netid = NULL;
+ int flag = 0;
+
+/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */
+
+ if (xprt->xp_netid) {
+ netid = strdup(xprt->xp_netid);
+ flag = 1;
+ } else if (nconf && nconf->nc_netid) {
+ netid = strdup(nconf->nc_netid);
+ flag = 1;
+ } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) {
+ netid = strdup(tnconf->nc_netid);
+ flag = 1;
+ freenetconfigent(tnconf);
+ } /* must have been created with svc_raw_create */
+ if ((netid == NULL) && (flag == 1)) {
+ return (FALSE);
+ }
+
+ rwlock_wrlock(&svc_lock);
+ if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
+ if (netid)
+ free(netid);
+ if (s->sc_dispatch == dispatch)
+ goto rpcb_it; /* he is registering another xptr */
+ rwlock_unlock(&svc_lock);
+ return (FALSE);
+ }
+ s = mem_alloc(sizeof (struct svc_callout));
+ if (s == NULL) {
+ if (netid)
+ free(netid);
+ rwlock_unlock(&svc_lock);
+ return (FALSE);
+ }
+
+ s->sc_prog = prog;
+ s->sc_vers = vers;
+ s->sc_dispatch = dispatch;
+ s->sc_netid = netid;
+ s->sc_next = svc_head;
+ svc_head = s;
+
+ if ((xprt->xp_netid == NULL) && (flag == 1) && netid)
+ ((SVCXPRT *) xprt)->xp_netid = strdup(netid);
+
+rpcb_it:
+ rwlock_unlock(&svc_lock);
+ /* now register the information with the local binder service */
+ if (nconf) {
+ /*LINTED const castaway*/
+ dummy = rpcb_set(prog, vers, (struct netconfig *) nconf,
+ &((SVCXPRT *) xprt)->xp_ltaddr);
+ return (dummy);
+ }
+ return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unreg(prog, vers)
+ const rpcprog_t prog;
+ const rpcvers_t vers;
+{
+ struct svc_callout *prev;
+ struct svc_callout *s;
+
+ /* unregister the information anyway */
+ (void) rpcb_unset(prog, vers, NULL);
+ rwlock_wrlock(&svc_lock);
+ while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) {
+ if (prev == NULL) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL;
+ if (s->sc_netid)
+ mem_free(s->sc_netid, sizeof (s->sc_netid) + 1);
+ mem_free(s, sizeof (struct svc_callout));
+ }
+ rwlock_unlock(&svc_lock);
+}
/* ********************** CALLOUT list related stuff ************* */
+#ifdef PORTMAP
/*
* Add a service program to the callout list.
* The dispatch routine will be called when a rpc request for this
@@ -162,23 +265,27 @@ svc_register(xprt, prog, vers, dispatch, protocol)
SVCXPRT *xprt;
u_long prog;
u_long vers;
- void (*dispatch)();
+ void (*dispatch) __P((struct svc_req *, SVCXPRT *));
int protocol;
{
struct svc_callout *prev;
- register struct svc_callout *s;
+ struct svc_callout *s;
+
+ assert(xprt != NULL);
+ assert(dispatch != NULL);
- if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+ if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) !=
+ NULL) {
if (s->sc_dispatch == dispatch)
goto pmap_it; /* he is registering another xptr */
return (FALSE);
}
- s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
- if (s == (struct svc_callout *)0) {
+ s = mem_alloc(sizeof(struct svc_callout));
+ if (s == NULL) {
return (FALSE);
}
- s->sc_prog = prog;
- s->sc_vers = vers;
+ s->sc_prog = (rpcprog_t)prog;
+ s->sc_vers = (rpcvers_t)vers;
s->sc_dispatch = dispatch;
s->sc_next = svc_head;
svc_head = s;
@@ -199,40 +306,46 @@ svc_unregister(prog, vers)
u_long vers;
{
struct svc_callout *prev;
- register struct svc_callout *s;
+ struct svc_callout *s;
- if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+ if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) ==
+ NULL)
return;
- if (prev == NULL_SVC) {
+ if (prev == NULL) {
svc_head = s->sc_next;
} else {
prev->sc_next = s->sc_next;
}
- s->sc_next = NULL_SVC;
- mem_free((char *) s, (u_int) sizeof(struct svc_callout));
+ s->sc_next = NULL;
+ mem_free(s, sizeof(struct svc_callout));
/* now unregister the information with the local binder service */
(void)pmap_unset(prog, vers);
}
+#endif /* PORTMAP */
/*
* Search the callout list for a program number, return the callout
* struct.
*/
static struct svc_callout *
-svc_find(prog, vers, prev)
- u_long prog;
- u_long vers;
+svc_find(prog, vers, prev, netid)
+ rpcprog_t prog;
+ rpcvers_t vers;
struct svc_callout **prev;
+ char *netid;
{
- register struct svc_callout *s, *p;
+ struct svc_callout *s, *p;
+
+ assert(prev != NULL);
- p = NULL_SVC;
- for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
- if ((s->sc_prog == prog) && (s->sc_vers == vers))
- goto done;
+ p = NULL;
+ for (s = svc_head; s != NULL; s = s->sc_next) {
+ if (((s->sc_prog == prog) && (s->sc_vers == vers)) &&
+ ((netid == NULL) || (s->sc_netid == NULL) ||
+ (strcmp(netid, s->sc_netid) == 0)))
+ break;
p = s;
}
-done:
*prev = p;
return (s);
}
@@ -244,19 +357,21 @@ done:
*/
bool_t
svc_sendreply(xprt, xdr_results, xdr_location)
- register SVCXPRT *xprt;
+ SVCXPRT *xprt;
xdrproc_t xdr_results;
caddr_t xdr_location;
{
- struct rpc_msg rply;
+ struct rpc_msg rply;
- rply.rm_direction = REPLY;
- rply.rm_reply.rp_stat = MSG_ACCEPTED;
- rply.acpted_rply.ar_verf = xprt->xp_verf;
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = SUCCESS;
rply.acpted_rply.ar_results.where = xdr_location;
rply.acpted_rply.ar_results.proc = xdr_results;
- return (SVC_REPLY(xprt, &rply));
+ return (SVC_REPLY(xprt, &rply));
}
/*
@@ -264,10 +379,12 @@ svc_sendreply(xprt, xdr_results, xdr_location)
*/
void
svcerr_noproc(xprt)
- register SVCXPRT *xprt;
+ SVCXPRT *xprt;
{
struct rpc_msg rply;
+ assert(xprt != NULL);
+
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
@@ -280,15 +397,17 @@ svcerr_noproc(xprt)
*/
void
svcerr_decode(xprt)
- register SVCXPRT *xprt;
+ SVCXPRT *xprt;
{
- struct rpc_msg rply;
+ struct rpc_msg rply;
- rply.rm_direction = REPLY;
- rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = GARBAGE_ARGS;
- SVC_REPLY(xprt, &rply);
+ SVC_REPLY(xprt, &rply);
}
/*
@@ -296,17 +415,61 @@ svcerr_decode(xprt)
*/
void
svcerr_systemerr(xprt)
- register SVCXPRT *xprt;
+ SVCXPRT *xprt;
{
- struct rpc_msg rply;
+ struct rpc_msg rply;
- rply.rm_direction = REPLY;
- rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = SYSTEM_ERR;
- SVC_REPLY(xprt, &rply);
+ SVC_REPLY(xprt, &rply);
}
+#if 0
+/*
+ * Tell RPC package to not complain about version errors to the client. This
+ * is useful when revving broadcast protocols that sit on a fixed address.
+ * There is really one (or should be only one) example of this kind of
+ * protocol: the portmapper (or rpc binder).
+ */
+void
+__svc_versquiet_on(xprt)
+ SVCXPRT *xprt;
+{
+ u_long tmp;
+
+ tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET;
+ xprt->xp_p3 = (caddr_t) tmp;
+}
+
+void
+__svc_versquiet_off(xprt)
+ SVCXPRT *xprt;
+{
+ u_long tmp;
+
+ tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET;
+ xprt->xp_p3 = (caddr_t) tmp;
+}
+
+void
+svc_versquiet(xprt)
+ SVCXPRT *xprt;
+{
+ __svc_versquiet_on(xprt);
+}
+
+int
+__svc_versquiet_get(xprt)
+ SVCXPRT *xprt;
+{
+ return ((int) xprt->xp_p3) & SVC_VERSQUIET;
+}
+#endif
+
/*
* Authentication error reply
*/
@@ -317,6 +480,8 @@ svcerr_auth(xprt, why)
{
struct rpc_msg rply;
+ assert(xprt != NULL);
+
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_DENIED;
rply.rjcted_rply.rj_stat = AUTH_ERROR;
@@ -332,21 +497,25 @@ svcerr_weakauth(xprt)
SVCXPRT *xprt;
{
+ assert(xprt != NULL);
+
svcerr_auth(xprt, AUTH_TOOWEAK);
}
/*
* Program unavailable error reply
*/
-void
+void
svcerr_noprog(xprt)
- register SVCXPRT *xprt;
+ SVCXPRT *xprt;
{
- struct rpc_msg rply;
+ struct rpc_msg rply;
- rply.rm_direction = REPLY;
- rply.rm_reply.rp_stat = MSG_ACCEPTED;
- rply.acpted_rply.ar_verf = xprt->xp_verf;
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = PROG_UNAVAIL;
SVC_REPLY(xprt, &rply);
}
@@ -354,20 +523,22 @@ svcerr_noprog(xprt)
/*
* Program version mismatch error reply
*/
-void
+void
svcerr_progvers(xprt, low_vers, high_vers)
- register SVCXPRT *xprt;
- u_long low_vers;
- u_long high_vers;
+ SVCXPRT *xprt;
+ rpcvers_t low_vers;
+ rpcvers_t high_vers;
{
struct rpc_msg rply;
+ assert(xprt != NULL);
+
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = PROG_MISMATCH;
- rply.acpted_rply.ar_vers.low = low_vers;
- rply.acpted_rply.ar_vers.high = high_vers;
+ rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers;
+ rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers;
SVC_REPLY(xprt, &rply);
}
@@ -404,90 +575,142 @@ void
svc_getreqset(readfds)
fd_set *readfds;
{
- svc_getreqset2(readfds, FD_SETSIZE);
+ int bit, fd;
+ fd_mask mask, *maskp;
+ int sock;
+
+ assert(readfds != NULL);
+
+ maskp = readfds->fds_bits;
+ for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) {
+ for (mask = *maskp++; (bit = ffs(mask)) != 0;
+ mask ^= (1 << (bit - 1))) {
+ /* sock has input waiting */
+ fd = sock + bit - 1;
+ svc_getreq_common(fd);
+ }
+ }
}
void
-svc_getreqset2(readfds, width)
- fd_set *readfds;
- int width;
+svc_getreq_common(fd)
+ int fd;
{
- enum xprt_stat stat;
+ SVCXPRT *xprt;
+ struct svc_req r;
struct rpc_msg msg;
int prog_found;
- u_long low_vers;
- u_long high_vers;
- struct svc_req r;
- register SVCXPRT *xprt;
- register int bit;
- register int sock;
- register fd_mask mask, *maskp;
+ rpcvers_t low_vers;
+ rpcvers_t high_vers;
+ enum xprt_stat stat;
char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+
msg.rm_call.cb_cred.oa_base = cred_area;
msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
-
- maskp = readfds->fds_bits;
- for (sock = 0; sock < width; sock += NFDBITS) {
- for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
- /* sock has input waiting */
- xprt = xports[sock + bit - 1];
- if (xprt == NULL)
- /* But do we control sock? */
- continue;
- /* now receive msgs from xprtprt (support batch calls) */
- do {
- if (SVC_RECV(xprt, &msg)) {
-
- /* now find the exported program and call it */
- register struct svc_callout *s;
- enum auth_stat why;
-
- r.rq_xprt = xprt;
- r.rq_prog = msg.rm_call.cb_prog;
- r.rq_vers = msg.rm_call.cb_vers;
- r.rq_proc = msg.rm_call.cb_proc;
- r.rq_cred = msg.rm_call.cb_cred;
- /* first authenticate the message */
- if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
- svcerr_auth(xprt, why);
- goto call_done;
- }
- /* now match message with a registered service*/
- prog_found = FALSE;
- low_vers = (u_long) - 1;
- high_vers = 0;
- for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
- if (s->sc_prog == r.rq_prog) {
- if (s->sc_vers == r.rq_vers) {
- (*s->sc_dispatch)(&r, xprt);
- goto call_done;
- } /* found correct version */
- prog_found = TRUE;
- if (s->sc_vers < low_vers)
- low_vers = s->sc_vers;
- if (s->sc_vers > high_vers)
- high_vers = s->sc_vers;
- } /* found correct program */
- }
- /*
- * if we got here, the program or version
- * is not served ...
- */
- if (prog_found)
- svcerr_progvers(xprt,
- low_vers, high_vers);
- else
- svcerr_noprog(xprt);
- /* Fall through to ... */
+ rwlock_rdlock(&svc_fd_lock);
+ xprt = xports[fd];
+ rwlock_unlock(&svc_fd_lock);
+ if (xprt == NULL)
+ /* But do we control sock? */
+ return;
+ /* now receive msgs from xprtprt (support batch calls) */
+ do {
+ if (SVC_RECV(xprt, &msg)) {
+
+ /* now find the exported program and call it */
+ struct svc_callout *s;
+ enum auth_stat why;
+
+ r.rq_xprt = xprt;
+ r.rq_prog = msg.rm_call.cb_prog;
+ r.rq_vers = msg.rm_call.cb_vers;
+ r.rq_proc = msg.rm_call.cb_proc;
+ r.rq_cred = msg.rm_call.cb_cred;
+ /* first authenticate the message */
+ if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
+ svcerr_auth(xprt, why);
+ goto call_done;
}
- call_done:
- if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
- SVC_DESTROY(xprt);
- break;
+ /* now match message with a registered service*/
+ prog_found = FALSE;
+ low_vers = (rpcvers_t) -1L;
+ high_vers = (rpcvers_t) 0L;
+ for (s = svc_head; s != NULL; s = s->sc_next) {
+ if (s->sc_prog == r.rq_prog) {
+ if (s->sc_vers == r.rq_vers) {
+ (*s->sc_dispatch)(&r, xprt);
+ goto call_done;
+ } /* found correct version */
+ prog_found = TRUE;
+ if (s->sc_vers < low_vers)
+ low_vers = s->sc_vers;
+ if (s->sc_vers > high_vers)
+ high_vers = s->sc_vers;
+ } /* found correct program */
}
- } while (stat == XPRT_MOREREQS);
- }
+ /*
+ * if we got here, the program or version
+ * is not served ...
+ */
+ if (prog_found)
+ svcerr_progvers(xprt, low_vers, high_vers);
+ else
+ svcerr_noprog(xprt);
+ /* Fall through to ... */
+ }
+ /*
+ * Check if the xprt has been disconnected in a
+ * recursive call in the service dispatch routine.
+ * If so, then break.
+ */
+ rwlock_rdlock(&svc_fd_lock);
+ if (xprt != xports[fd]) {
+ rwlock_unlock(&svc_fd_lock);
+ break;
+ }
+ rwlock_unlock(&svc_fd_lock);
+call_done:
+ if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+ SVC_DESTROY(xprt);
+ break;
+ }
+ } while (stat == XPRT_MOREREQS);
+}
+
+
+void
+svc_getreq_poll(pfdp, pollretval)
+ struct pollfd *pfdp;
+ int pollretval;
+{
+ int i;
+ int fds_found;
+
+ for (i = fds_found = 0; fds_found < pollretval; i++) {
+ struct pollfd *p = &pfdp[i];
+
+ if (p->revents) {
+ /* fd has input waiting */
+ fds_found++;
+ /*
+ * We assume that this function is only called
+ * via someone _select()ing from svc_fdset or
+ * _poll()ing from svc_pollset[]. Thus it's safe
+ * to handle the POLLNVAL event by simply turning
+ * the corresponding bit off in svc_fdset. The
+ * svc_pollset[] array is derived from svc_fdset
+ * and so will also be updated eventually.
+ *
+ * XXX Should we do an xprt_unregister() instead?
+ */
+ if (p->revents & POLLNVAL) {
+ rwlock_wrlock(&svc_fd_lock);
+ FD_CLR(p->fd, &svc_fdset);
+ rwlock_unlock(&svc_fd_lock);
+ } else
+ svc_getreq_common(p->fd);
+ }
}
}
diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c
index fa1dca7ce7ec..48d65b0a839b 100644
--- a/lib/libc/rpc/svc_auth.c
+++ b/lib/libc/rpc/svc_auth.c
@@ -1,3 +1,5 @@
+/* $NetBSD: svc_auth.c,v 1.12 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -30,14 +32,12 @@
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
*/
-#ident "@(#)svc_auth.c 1.16 94/04/24 SMI"
+/* #ident "@(#)svc_auth.c 1.16 94/04/24 SMI" */
-#if !defined(lint) && defined(SCCSIDS)
#if 0
+#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
-#else
-static const char rcsid[] =
- "$FreeBSD$";
+static const char rcsid[] = "$FreeBSD$";
#endif
#endif
@@ -46,20 +46,12 @@ static const char rcsid[] =
*
*/
-#ifdef _KERNEL
-#include <sys/param.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <rpc/auth.h>
-#include <rpc/clnt.h>
-#include <rpc/rpc_msg.h>
-#include <rpc/svc.h>
-#include <rpc/svc_auth.h>
-#else
-#include <stdlib.h>
-#include <rpc/rpc.h>
-#endif
+#include "reentrant.h"
+#include "namespace.h"
#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include "un-namespace.h"
/*
* svcauthsw is the bdevsw of server side authentication.
@@ -71,20 +63,15 @@ static const char rcsid[] =
*
* enum auth_stat
* flavorx_auth(rqst, msg)
- * register struct svc_req *rqst;
- * register struct rpc_msg *msg;
+ * struct svc_req *rqst;
+ * struct rpc_msg *msg;
*
*/
-enum auth_stat _svcauth_null(); /* no authentication */
-enum auth_stat _svcauth_unix(); /* (system) unix style (uid, gids) */
-enum auth_stat _svcauth_short(); /* short hand unix style */
-enum auth_stat _svcauth_des(); /* des style */
-
/* declarations to allow servers to specify new authentication flavors */
struct authsvc {
int flavor;
- enum auth_stat (*handler)();
+ enum auth_stat (*handler) __P((struct svc_req *, struct rpc_msg *));
struct authsvc *next;
};
static struct authsvc *Auths = NULL;
@@ -109,11 +96,15 @@ static struct authsvc *Auths = NULL;
*/
enum auth_stat
_authenticate(rqst, msg)
- register struct svc_req *rqst;
+ struct svc_req *rqst;
struct rpc_msg *msg;
{
- register int cred_flavor;
- register struct authsvc *asp;
+ int cred_flavor;
+ struct authsvc *asp;
+ enum auth_stat dummy;
+ extern mutex_t authsvc_lock;
+
+/* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
rqst->rq_cred = msg->rm_call.cb_cred;
rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
@@ -121,34 +112,35 @@ _authenticate(rqst, msg)
cred_flavor = rqst->rq_cred.oa_flavor;
switch (cred_flavor) {
case AUTH_NULL:
- return(_svcauth_null(rqst, msg));
- case AUTH_UNIX:
- return(_svcauth_unix(rqst, msg));
+ dummy = _svcauth_null(rqst, msg);
+ return (dummy);
+ case AUTH_SYS:
+ dummy = _svcauth_unix(rqst, msg);
+ return (dummy);
case AUTH_SHORT:
- return(_svcauth_short(rqst, msg));
- /*
- * We leave AUTH_DES turned off by default because svcauth_des()
- * needs getpublickey(), which is in librpcsvc, not libc. If we
- * included AUTH_DES as a built-in flavor, programs that don't
- * have -lrpcsvc in their Makefiles wouldn't link correctly, even
- * though they don't use AUTH_DES. And I'm too lazy to go through
- * the tree looking for all of them.
- */
+ dummy = _svcauth_short(rqst, msg);
+ return (dummy);
#ifdef DES_BUILTIN
case AUTH_DES:
- return(_svcauth_des(rqst, msg));
+ dummy = _svcauth_des(rqst, msg);
+ return (dummy);
#endif
+ default:
+ break;
}
/* flavor doesn't match any of the builtin types, so try new ones */
+ mutex_lock(&authsvc_lock);
for (asp = Auths; asp; asp = asp->next) {
if (asp->flavor == cred_flavor) {
enum auth_stat as;
as = (*asp->handler)(rqst, msg);
+ mutex_unlock(&authsvc_lock);
return (as);
}
}
+ mutex_unlock(&authsvc_lock);
return (AUTH_REJECTEDCRED);
}
@@ -178,14 +170,15 @@ _svcauth_null(rqst, msg)
int
svc_auth_reg(cred_flavor, handler)
- register int cred_flavor;
- enum auth_stat (*handler)();
+ int cred_flavor;
+ enum auth_stat (*handler) __P((struct svc_req *, struct rpc_msg *));
{
- register struct authsvc *asp;
+ struct authsvc *asp;
+ extern mutex_t authsvc_lock;
switch (cred_flavor) {
case AUTH_NULL:
- case AUTH_UNIX:
+ case AUTH_SYS:
case AUTH_SHORT:
#ifdef DES_BUILTIN
case AUTH_DES:
@@ -194,22 +187,26 @@ svc_auth_reg(cred_flavor, handler)
return (1);
default:
+ mutex_lock(&authsvc_lock);
for (asp = Auths; asp; asp = asp->next) {
if (asp->flavor == cred_flavor) {
/* already registered */
+ mutex_unlock(&authsvc_lock);
return (1);
}
}
/* this is a new one, so go ahead and register it */
- asp = (struct authsvc *)mem_alloc(sizeof (*asp));
+ asp = mem_alloc(sizeof (*asp));
if (asp == NULL) {
+ mutex_unlock(&authsvc_lock);
return (-1);
}
asp->flavor = cred_flavor;
asp->handler = handler;
asp->next = Auths;
Auths = asp;
+ mutex_unlock(&authsvc_lock);
break;
}
return (0);
diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c
index f3af780f1683..0d363c132bac 100644
--- a/lib/libc/rpc/svc_auth_des.c
+++ b/lib/libc/rpc/svc_auth_des.c
@@ -46,6 +46,8 @@
*
*/
+#include "reentrant.h"
+#include "namespace.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -60,6 +62,7 @@
#include <rpc/svc.h>
#include <rpc/rpc_msg.h>
#include <rpc/svc_auth.h>
+#include "libc_private.h"
#if defined(LIBC_SCCS) && !defined(lint)
/* from: static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; */
@@ -190,7 +193,7 @@ _svcauth_des(rqst, msg)
}
} else { /* ADN_NICKNAME */
sid = (short)cred->adc_nickname;
- if (sid >= AUTHDES_CACHESZ) {
+ if (sid < 0 || sid >= AUTHDES_CACHESZ) {
debug("bad nickname");
return (AUTH_BADCRED); /* garbled credential */
}
diff --git a/lib/libc/rpc/svc_auth_unix.c b/lib/libc/rpc/svc_auth_unix.c
index 4e800e5e2aa3..ba6e483012b5 100644
--- a/lib/libc/rpc/svc_auth_unix.c
+++ b/lib/libc/rpc/svc_auth_unix.c
@@ -27,9 +27,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";*/
+static char *sccsid = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -44,30 +45,37 @@ static char *rcsid = "$FreeBSD$";
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "namespace.h"
+#include <assert.h>
#include <stdio.h>
#include <string.h>
+
#include <rpc/rpc.h>
+#include "un-namespace.h"
/*
* Unix longhand authenticator
*/
enum auth_stat
_svcauth_unix(rqst, msg)
- register struct svc_req *rqst;
- register struct rpc_msg *msg;
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
{
- register enum auth_stat stat;
+ enum auth_stat stat;
XDR xdrs;
- register struct authunix_parms *aup;
- register int32_t *buf;
+ struct authunix_parms *aup;
+ int32_t *buf;
struct area {
struct authunix_parms area_aup;
char area_machname[MAX_MACHINE_NAME+1];
int area_gids[NGRPS];
} *area;
u_int auth_len;
- int str_len, gid_len;
- register int i;
+ size_t str_len, gid_len;
+ u_int i;
+
+ assert(rqst != NULL);
+ assert(msg != NULL);
area = (struct area *) rqst->rq_clntcred;
aup = &area->area_aup;
@@ -77,34 +85,34 @@ _svcauth_unix(rqst, msg)
xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
buf = XDR_INLINE(&xdrs, auth_len);
if (buf != NULL) {
- aup->aup_time = IXDR_GET_LONG(buf);
- str_len = IXDR_GET_U_LONG(buf);
+ aup->aup_time = IXDR_GET_INT32(buf);
+ str_len = (size_t)IXDR_GET_U_INT32(buf);
if (str_len > MAX_MACHINE_NAME) {
stat = AUTH_BADCRED;
goto done;
}
- memcpy(aup->aup_machname, (caddr_t)buf, (u_int)str_len);
+ memmove(aup->aup_machname, buf, str_len);
aup->aup_machname[str_len] = 0;
str_len = RNDUP(str_len);
buf += str_len / sizeof (int32_t);
- aup->aup_uid = IXDR_GET_LONG(buf);
- aup->aup_gid = IXDR_GET_LONG(buf);
- gid_len = IXDR_GET_U_LONG(buf);
+ aup->aup_uid = (int)IXDR_GET_INT32(buf);
+ aup->aup_gid = (int)IXDR_GET_INT32(buf);
+ gid_len = (size_t)IXDR_GET_U_INT32(buf);
if (gid_len > NGRPS) {
stat = AUTH_BADCRED;
goto done;
}
aup->aup_len = gid_len;
for (i = 0; i < gid_len; i++) {
- aup->aup_gids[i] = IXDR_GET_LONG(buf);
+ aup->aup_gids[i] = (int)IXDR_GET_INT32(buf);
}
/*
* five is the smallest unix credentials structure -
* timestamp, hostname len (0), uid, gid, and gids len (0).
*/
if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
- (void) printf("bad auth_len gid %d str %d auth %d\n",
- gid_len, str_len, auth_len);
+ (void) printf("bad auth_len gid %ld str %ld auth %u\n",
+ (long)gid_len, (long)str_len, auth_len);
stat = AUTH_BADCRED;
goto done;
}
@@ -115,13 +123,13 @@ _svcauth_unix(rqst, msg)
goto done;
}
- /* get the verifier */
+ /* get the verifier */
if ((u_int)msg->rm_call.cb_verf.oa_length) {
- rqst->rq_xprt->xp_verf.oa_flavor =
+ rqst->rq_xprt->xp_verf.oa_flavor =
msg->rm_call.cb_verf.oa_flavor;
- rqst->rq_xprt->xp_verf.oa_base =
+ rqst->rq_xprt->xp_verf.oa_base =
msg->rm_call.cb_verf.oa_base;
- rqst->rq_xprt->xp_verf.oa_length =
+ rqst->rq_xprt->xp_verf.oa_length =
msg->rm_call.cb_verf.oa_length;
} else {
rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
@@ -139,7 +147,7 @@ done:
* Looks up longhand in a cache.
*/
/*ARGSUSED*/
-enum auth_stat
+enum auth_stat
_svcauth_short(rqst, msg)
struct svc_req *rqst;
struct rpc_msg *msg;
diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c
new file mode 100644
index 000000000000..03ace97f964c
--- /dev/null
+++ b/lib/libc/rpc/svc_dg.c
@@ -0,0 +1,603 @@
+/* $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)svc_dg.c 1.17 94/04/24 SMI" */
+
+
+/*
+ * svc_dg.c, Server side for connectionless RPC.
+ *
+ * Does some caching in the hopes of achieving execute-at-most-once semantics.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/svc_dg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef RPC_CACHE_DEBUG
+#include <netconfig.h>
+#include <netdir.h>
+#endif
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+#define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2))
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+static void svc_dg_ops __P((SVCXPRT *));
+static enum xprt_stat svc_dg_stat __P((SVCXPRT *));
+static bool_t svc_dg_recv __P((SVCXPRT *, struct rpc_msg *));
+static bool_t svc_dg_reply __P((SVCXPRT *, struct rpc_msg *));
+static bool_t svc_dg_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static bool_t svc_dg_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static void svc_dg_destroy __P((SVCXPRT *));
+static bool_t svc_dg_control __P((SVCXPRT *, const u_int, void *));
+static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, size_t *));
+static void cache_set __P((SVCXPRT *, size_t));
+int svc_dg_enablecache __P((SVCXPRT *, u_int));
+
+/*
+ * Usage:
+ * xprt = svc_dg_create(sock, sendsize, recvsize);
+ * Does other connectionless specific initializations.
+ * Once *xprt is initialized, it is registered.
+ * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
+ * system defaults are chosen.
+ * The routines returns NULL if a problem occurred.
+ */
+static const char svc_dg_str[] = "svc_dg_create: %s";
+static const char svc_dg_err1[] = "could not get transport information";
+static const char svc_dg_err2[] = " transport does not support data transfer";
+static const char __no_mem_str[] = "out of memory";
+
+SVCXPRT *
+svc_dg_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct svc_dg_data *su = NULL;
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ if (!__rpc_fd2sockinfo(fd, &si)) {
+ warnx(svc_dg_str, svc_dg_err1);
+ return (NULL);
+ }
+ /*
+ * Find the receive and the send size
+ */
+ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+ recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+ if ((sendsize == 0) || (recvsize == 0)) {
+ warnx(svc_dg_str, svc_dg_err2);
+ return (NULL);
+ }
+
+ xprt = mem_alloc(sizeof (SVCXPRT));
+ if (xprt == NULL)
+ goto freedata;
+ memset(xprt, 0, sizeof (SVCXPRT));
+
+ su = mem_alloc(sizeof (*su));
+ if (su == NULL)
+ goto freedata;
+ su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4;
+ if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL)
+ goto freedata;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
+ XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_fd = fd;
+ xprt->xp_p2 = (caddr_t)(void *)su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ svc_dg_ops(xprt);
+ xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+
+ slen = sizeof ss;
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
+ goto freedata;
+ xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
+ xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
+ xprt->xp_ltaddr.len = slen;
+ memcpy(xprt->xp_ltaddr.buf, &ss, slen);
+
+ xprt_register(xprt);
+ return (xprt);
+freedata:
+ (void) warnx(svc_dg_str, __no_mem_str);
+ if (xprt) {
+ if (su)
+ (void) mem_free(su, sizeof (*su));
+ (void) mem_free(xprt, sizeof (SVCXPRT));
+ }
+ return (NULL);
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svc_dg_stat(xprt)
+ SVCXPRT *xprt;
+{
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svc_dg_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_dg_data *su = su_data(xprt);
+ XDR *xdrs = &(su->su_xdrs);
+ char *reply;
+ struct sockaddr_storage ss;
+ socklen_t alen;
+ size_t replylen;
+ int rlen;
+
+again:
+ alen = sizeof (struct sockaddr_storage);
+ rlen = _recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz, 0,
+ (struct sockaddr *)(void *)&ss, &alen);
+ if (rlen == -1 && errno == EINTR)
+ goto again;
+ if (rlen == -1 || (rlen < 4 * sizeof (u_int32_t)))
+ return (FALSE);
+ if (xprt->xp_rtaddr.len < alen) {
+ if (xprt->xp_rtaddr.len != 0)
+ mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.len);
+ xprt->xp_rtaddr.buf = mem_alloc(alen);
+ xprt->xp_rtaddr.len = alen;
+ }
+ memcpy(xprt->xp_rtaddr.buf, &ss, alen);
+#ifdef PORTMAP
+ if (ss.ss_family == AF_INET) {
+ xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf;
+ xprt->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg)) {
+ return (FALSE);
+ }
+ su->su_xid = msg->rm_xid;
+ if (su->su_cache != NULL) {
+ if (cache_get(xprt, msg, &reply, &replylen)) {
+ (void)_sendto(xprt->xp_fd, reply, replylen, 0,
+ (struct sockaddr *)(void *)&ss, alen);
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static bool_t
+svc_dg_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_dg_data *su = su_data(xprt);
+ XDR *xdrs = &(su->su_xdrs);
+ bool_t stat = FALSE;
+ size_t slen;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (xdr_replymsg(xdrs, msg)) {
+ slen = XDR_GETPOS(xdrs);
+ if (_sendto(xprt->xp_fd, rpc_buffer(xprt), slen, 0,
+ (struct sockaddr *)xprt->xp_rtaddr.buf,
+ (socklen_t)xprt->xp_rtaddr.len) == slen) {
+ stat = TRUE;
+ if (su->su_cache)
+ cache_set(xprt, slen);
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svc_dg_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ return (*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr);
+}
+
+static bool_t
+svc_dg_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return (*xdr_args)(xdrs, args_ptr);
+}
+
+static void
+svc_dg_destroy(xprt)
+ SVCXPRT *xprt;
+{
+ struct svc_dg_data *su = su_data(xprt);
+
+ xprt_unregister(xprt);
+ if (xprt->xp_fd != -1)
+ (void)_close(xprt->xp_fd);
+ XDR_DESTROY(&(su->su_xdrs));
+ (void) mem_free(rpc_buffer(xprt), su->su_iosz);
+ (void) mem_free(su, sizeof (*su));
+ if (xprt->xp_rtaddr.buf)
+ (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+ if (xprt->xp_ltaddr.buf)
+ (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+ if (xprt->xp_tp)
+ (void) free(xprt->xp_tp);
+ (void) mem_free(xprt, sizeof (SVCXPRT));
+}
+
+static bool_t
+/*ARGSUSED*/
+svc_dg_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
+}
+
+static void
+svc_dg_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+ extern mutex_t ops_lock;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_dg_recv;
+ ops.xp_stat = svc_dg_stat;
+ ops.xp_getargs = svc_dg_getargs;
+ ops.xp_reply = svc_dg_reply;
+ ops.xp_freeargs = svc_dg_freeargs;
+ ops.xp_destroy = svc_dg_destroy;
+ ops2.xp_control = svc_dg_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+/* The CACHING COMPONENT */
+
+/*
+ * Could have been a separate file, but some part of it depends upon the
+ * private structure of the client handle.
+ *
+ * Fifo cache for cl server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4 /* 75% sparse */
+
+#define ALLOC(type, size) \
+ (type *) mem_alloc((sizeof (type) * (size)))
+
+#define MEMZERO(addr, type, size) \
+ (void) memset((void *) (addr), 0, sizeof (type) * (int) (size))
+
+#define FREE(addr, type, size) \
+ mem_free((addr), (sizeof (type) * (size)))
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+ /*
+ * Index into cache is xid, proc, vers, prog and address
+ */
+ u_int32_t cache_xid;
+ rpcproc_t cache_proc;
+ rpcvers_t cache_vers;
+ rpcprog_t cache_prog;
+ struct netbuf cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char *cache_reply;
+ size_t cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+/*
+ * The entire cache
+ */
+struct cl_cache {
+ u_int uc_size; /* size of cache */
+ cache_ptr *uc_entries; /* hash table of entries in cache */
+ cache_ptr *uc_fifo; /* fifo list of entries in cache */
+ u_int uc_nextvictim; /* points to next victim in fifo list */
+ rpcprog_t uc_prog; /* saved program number */
+ rpcvers_t uc_vers; /* saved version number */
+ rpcproc_t uc_proc; /* saved procedure number */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid) \
+ (xid % (SPARSENESS * ((struct cl_cache *) \
+ su_data(transp)->su_cache)->uc_size))
+
+extern mutex_t dupreq_lock;
+
+/*
+ * Enable use of the cache. Returns 1 on success, 0 on failure.
+ * Note: there is no disable.
+ */
+static const char cache_enable_str[] = "svc_enablecache: %s %s";
+static const char alloc_err[] = "could not allocate cache ";
+static const char enable_err[] = "cache already enabled";
+
+int
+svc_dg_enablecache(transp, size)
+ SVCXPRT *transp;
+ u_int size;
+{
+ struct svc_dg_data *su = su_data(transp);
+ struct cl_cache *uc;
+
+ mutex_lock(&dupreq_lock);
+ if (su->su_cache != NULL) {
+ (void) warnx(cache_enable_str, enable_err, " ");
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ uc = ALLOC(struct cl_cache, 1);
+ if (uc == NULL) {
+ warnx(cache_enable_str, alloc_err, " ");
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ uc->uc_size = size;
+ uc->uc_nextvictim = 0;
+ uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+ if (uc->uc_entries == NULL) {
+ warnx(cache_enable_str, alloc_err, "data");
+ FREE(uc, struct cl_cache, 1);
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ MEMZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ uc->uc_fifo = ALLOC(cache_ptr, size);
+ if (uc->uc_fifo == NULL) {
+ warnx(cache_enable_str, alloc_err, "fifo");
+ FREE(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ FREE(uc, struct cl_cache, 1);
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ MEMZERO(uc->uc_fifo, cache_ptr, size);
+ su->su_cache = (char *)(void *)uc;
+ mutex_unlock(&dupreq_lock);
+ return (1);
+}
+
+/*
+ * Set an entry in the cache. It assumes that the uc entry is set from
+ * the earlier call to cache_get() for the same procedure. This will always
+ * happen because cache_get() is calle by svc_dg_recv and cache_set() is called
+ * by svc_dg_reply(). All this hoopla because the right RPC parameters are
+ * not available at svc_dg_reply time.
+ */
+
+static const char cache_set_str[] = "cache_set: %s";
+static const char cache_set_err1[] = "victim not found";
+static const char cache_set_err2[] = "victim alloc failed";
+static const char cache_set_err3[] = "could not allocate new rpc buffer";
+
+static void
+cache_set(xprt, replylen)
+ SVCXPRT *xprt;
+ size_t replylen;
+{
+ cache_ptr victim;
+ cache_ptr *vicp;
+ struct svc_dg_data *su = su_data(xprt);
+ struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+ u_int loc;
+ char *newbuf;
+#ifdef RPC_CACHE_DEBUG
+ struct netconfig *nconf;
+ char *uaddr;
+#endif
+
+ mutex_lock(&dupreq_lock);
+ /*
+ * Find space for the new entry, either by
+ * reusing an old entry, or by mallocing a new one
+ */
+ victim = uc->uc_fifo[uc->uc_nextvictim];
+ if (victim != NULL) {
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ for (vicp = &uc->uc_entries[loc];
+ *vicp != NULL && *vicp != victim;
+ vicp = &(*vicp)->cache_next)
+ ;
+ if (*vicp == NULL) {
+ warnx(cache_set_str, cache_set_err1);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ *vicp = victim->cache_next; /* remove from cache */
+ newbuf = victim->cache_reply;
+ } else {
+ victim = ALLOC(struct cache_node, 1);
+ if (victim == NULL) {
+ warnx(cache_set_str, cache_set_err2);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ newbuf = mem_alloc(su->su_iosz);
+ if (newbuf == NULL) {
+ warnx(cache_set_str, cache_set_err3);
+ FREE(victim, struct cache_node, 1);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ }
+
+ /*
+ * Store it away
+ */
+#ifdef RPC_CACHE_DEBUG
+ if (nconf = getnetconfigent(xprt->xp_netid)) {
+ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+ freenetconfigent(nconf);
+ printf(
+ "cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+ su->su_xid, uc->uc_prog, uc->uc_vers,
+ uc->uc_proc, uaddr);
+ free(uaddr);
+ }
+#endif
+ victim->cache_replylen = replylen;
+ victim->cache_reply = rpc_buffer(xprt);
+ rpc_buffer(xprt) = newbuf;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt),
+ su->su_iosz, XDR_ENCODE);
+ victim->cache_xid = su->su_xid;
+ victim->cache_proc = uc->uc_proc;
+ victim->cache_vers = uc->uc_vers;
+ victim->cache_prog = uc->uc_prog;
+ victim->cache_addr = xprt->xp_rtaddr;
+ victim->cache_addr.buf = ALLOC(char, xprt->xp_rtaddr.len);
+ (void) memcpy(victim->cache_addr.buf, xprt->xp_rtaddr.buf,
+ (size_t)xprt->xp_rtaddr.len);
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ victim->cache_next = uc->uc_entries[loc];
+ uc->uc_entries[loc] = victim;
+ uc->uc_fifo[uc->uc_nextvictim++] = victim;
+ uc->uc_nextvictim %= uc->uc_size;
+ mutex_unlock(&dupreq_lock);
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found and set the stage for cache_set()
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ size_t *replylenp;
+{
+ u_int loc;
+ cache_ptr ent;
+ struct svc_dg_data *su = su_data(xprt);
+ struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+#ifdef RPC_CACHE_DEBUG
+ struct netconfig *nconf;
+ char *uaddr;
+#endif
+
+ mutex_lock(&dupreq_lock);
+ loc = CACHE_LOC(xprt, su->su_xid);
+ for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+ if (ent->cache_xid == su->su_xid &&
+ ent->cache_proc == msg->rm_call.cb_proc &&
+ ent->cache_vers == msg->rm_call.cb_vers &&
+ ent->cache_prog == msg->rm_call.cb_prog &&
+ ent->cache_addr.len == xprt->xp_rtaddr.len &&
+ (memcmp(ent->cache_addr.buf, xprt->xp_rtaddr.buf,
+ xprt->xp_rtaddr.len) == 0)) {
+#ifdef RPC_CACHE_DEBUG
+ if (nconf = getnetconfigent(xprt->xp_netid)) {
+ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+ freenetconfigent(nconf);
+ printf(
+ "cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+ su->su_xid, msg->rm_call.cb_prog,
+ msg->rm_call.cb_vers,
+ msg->rm_call.cb_proc, uaddr);
+ free(uaddr);
+ }
+#endif
+ *replyp = ent->cache_reply;
+ *replylenp = ent->cache_replylen;
+ mutex_unlock(&dupreq_lock);
+ return (1);
+ }
+ }
+ /*
+ * Failed to find entry
+ * Remember a few things so we can do a set later
+ */
+ uc->uc_proc = msg->rm_call.cb_proc;
+ uc->uc_vers = msg->rm_call.cb_vers;
+ uc->uc_prog = msg->rm_call.cb_prog;
+ mutex_unlock(&dupreq_lock);
+ return (0);
+}
diff --git a/lib/libc/rpc/svc_generic.c b/lib/libc/rpc/svc_generic.c
new file mode 100644
index 000000000000..773118d62e36
--- /dev/null
+++ b/lib/libc/rpc/svc_generic.c
@@ -0,0 +1,313 @@
+/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" */
+
+#if 0
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
+#endif
+#endif
+
+/*
+ * svc_generic.c, Server side for RPC.
+ *
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+extern int __svc_vc_setflag __P((SVCXPRT *, int));
+
+/*
+ * The highest level interface for server creation.
+ * It tries for all the nettokens in that particular class of token
+ * and returns the number of handles it can create and/or find.
+ *
+ * It creates a link list of all the handles it could create.
+ * If svc_create() is called multiple times, it uses the handle
+ * created earlier instead of creating a new handle every time.
+ */
+int
+svc_create(dispatch, prognum, versnum, nettype)
+ void (*dispatch) __P((struct svc_req *, SVCXPRT *));
+ rpcprog_t prognum; /* Program number */
+ rpcvers_t versnum; /* Version number */
+ const char *nettype; /* Networktype token */
+{
+ struct xlist {
+ SVCXPRT *xprt; /* Server handle */
+ struct xlist *next; /* Next item */
+ } *l;
+ static struct xlist *xprtlist; /* A link list of all the handles */
+ int num = 0;
+ SVCXPRT *xprt;
+ struct netconfig *nconf;
+ void *handle;
+ extern mutex_t xprtlist_lock;
+
+/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
+
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ warnx("svc_create: unknown protocol");
+ return (0);
+ }
+ while ((nconf = __rpc_getconf(handle)) != NULL) {
+ mutex_lock(&xprtlist_lock);
+ for (l = xprtlist; l; l = l->next) {
+ if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
+ /* Found an old one, use it */
+ (void) rpcb_unset(prognum, versnum, nconf);
+ if (svc_reg(l->xprt, prognum, versnum,
+ dispatch, nconf) == FALSE)
+ warnx(
+ "svc_create: could not register prog %u vers %u on %s",
+ (unsigned)prognum, (unsigned)versnum,
+ nconf->nc_netid);
+ else
+ num++;
+ break;
+ }
+ }
+ if (l == NULL) {
+ /* It was not found. Now create a new one */
+ xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
+ if (xprt) {
+ l = (struct xlist *)malloc(sizeof (*l));
+ if (l == NULL) {
+ warnx("svc_create: no memory");
+ mutex_unlock(&xprtlist_lock);
+ return (0);
+ }
+ l->xprt = xprt;
+ l->next = xprtlist;
+ xprtlist = l;
+ num++;
+ }
+ }
+ mutex_unlock(&xprtlist_lock);
+ }
+ __rpc_endconf(handle);
+ /*
+ * In case of num == 0; the error messages are generated by the
+ * underlying layers; and hence not needed here.
+ */
+ return (num);
+}
+
+/*
+ * The high level interface to svc_tli_create().
+ * It tries to create a server for "nconf" and registers the service
+ * with the rpcbind. It calls svc_tli_create();
+ */
+SVCXPRT *
+svc_tp_create(dispatch, prognum, versnum, nconf)
+ void (*dispatch) __P((struct svc_req *, SVCXPRT *));
+ rpcprog_t prognum; /* Program number */
+ rpcvers_t versnum; /* Version number */
+ const struct netconfig *nconf; /* Netconfig structure for the network */
+{
+ SVCXPRT *xprt;
+
+ if (nconf == NULL) {
+ warnx(
+ "svc_tp_create: invalid netconfig structure for prog %u vers %u",
+ (unsigned)prognum, (unsigned)versnum);
+ return (NULL);
+ }
+ xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+ if (xprt == NULL) {
+ return (NULL);
+ }
+ /*LINTED const castaway*/
+ (void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf);
+ if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
+ warnx(
+ "svc_tp_create: Could not register prog %u vers %u on %s",
+ (unsigned)prognum, (unsigned)versnum,
+ nconf->nc_netid);
+ SVC_DESTROY(xprt);
+ return (NULL);
+ }
+ return (xprt);
+}
+
+/*
+ * If fd is RPC_ANYFD, then it opens a fd for the given transport
+ * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
+ * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
+ * NULL bindadr and Connection oriented transports, the value of qlen
+ * is set to 8.
+ *
+ * If sendsz or recvsz are zero, their default values are chosen.
+ */
+SVCXPRT *
+svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
+ int fd; /* Connection end point */
+ const struct netconfig *nconf; /* Netconfig struct for nettoken */
+ const struct t_bind *bindaddr; /* Local bind address */
+ u_int sendsz; /* Max sendsize */
+ u_int recvsz; /* Max recvsize */
+{
+ SVCXPRT *xprt = NULL; /* service handle */
+ bool_t madefd = FALSE; /* whether fd opened here */
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ if (fd == RPC_ANYFD) {
+ if (nconf == NULL) {
+ warnx("svc_tli_create: invalid netconfig");
+ return (NULL);
+ }
+ fd = __rpc_nconf2fd(nconf);
+ if (fd == -1) {
+ warnx(
+ "svc_tli_create: could not open connection for %s",
+ nconf->nc_netid);
+ return (NULL);
+ }
+ __rpc_nconf2sockinfo(nconf, &si);
+ madefd = TRUE;
+ } else {
+ /*
+ * It is an open descriptor. Get the transport info.
+ */
+ if (!__rpc_fd2sockinfo(fd, &si)) {
+ warnx(
+ "svc_tli_create: could not get transport information");
+ return (NULL);
+ }
+ }
+
+ /*
+ * If the fd is unbound, try to bind it.
+ */
+ if (madefd || !__rpc_sockisbound(fd)) {
+ if (bindaddr == NULL) {
+ if (bindresvport(fd, NULL) < 0) {
+ memset(&ss, 0, sizeof ss);
+ ss.ss_family = si.si_af;
+ ss.ss_len = si.si_alen;
+ if (_bind(fd, (struct sockaddr *)(void *)&ss,
+ (socklen_t)si.si_alen) < 0) {
+ warnx(
+ "svc_tli_create: could not bind to anonymous port");
+ goto freedata;
+ }
+ }
+ _listen(fd, SOMAXCONN);
+ } else {
+ if (_bind(fd,
+ (struct sockaddr *)(void *)&bindaddr->addr.buf,
+ (socklen_t)si.si_alen) < 0) {
+ warnx(
+ "svc_tli_create: could not bind to requested address");
+ goto freedata;
+ }
+ _listen(fd, (int)bindaddr->qlen);
+ }
+
+ }
+ /*
+ * call transport specific function.
+ */
+ switch (si.si_socktype) {
+ case SOCK_STREAM:
+ slen = sizeof ss;
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
+ == 0) {
+ /* accepted socket */
+ xprt = svc_fd_create(fd, sendsz, recvsz);
+ } else
+ xprt = svc_vc_create(fd, sendsz, recvsz);
+ if (!nconf || !xprt)
+ break;
+#if 0
+ /* XXX fvdl */
+ if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
+ strcmp(nconf->nc_protofmly, "inet6") == 0)
+ (void) __svc_vc_setflag(xprt, TRUE);
+#endif
+ break;
+ case SOCK_DGRAM:
+ xprt = svc_dg_create(fd, sendsz, recvsz);
+ break;
+ default:
+ warnx("svc_tli_create: bad service type");
+ goto freedata;
+ }
+
+ if (xprt == NULL)
+ /*
+ * The error messages here are spitted out by the lower layers:
+ * svc_vc_create(), svc_fd_create() and svc_dg_create().
+ */
+ goto freedata;
+
+ /* Fill in type of service */
+ xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
+
+ if (nconf) {
+ xprt->xp_netid = strdup(nconf->nc_netid);
+ xprt->xp_tp = strdup(nconf->nc_device);
+ }
+ return (xprt);
+
+freedata:
+ if (madefd)
+ (void)_close(fd);
+ if (xprt) {
+ if (!madefd) /* so that svc_destroy doesnt close fd */
+ xprt->xp_fd = RPC_ANYFD;
+ SVC_DESTROY(xprt);
+ }
+ return (NULL);
+}
diff --git a/lib/libc/rpc/svc_raw.c b/lib/libc/rpc/svc_raw.c
index 472615253428..5ab10f8a77dc 100644
--- a/lib/libc/rpc/svc_raw.c
+++ b/lib/libc/rpc/svc_raw.c
@@ -1,3 +1,5 @@
+/* $NetBSD: svc_raw.c,v 1.14 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,12 +28,18 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC";*/
+/* #ident "@(#)svc_raw.c 1.16 94/04/24 SMI" */
+
+#if 0
+#if defined(SCCSIDS) && !defined(lint)
+static char sccsid[] = "@(#)svc_raw.c 1.25 89/01/31 Copyr 1984 Sun Micro";
static char *rcsid = "$FreeBSD$";
#endif
+#endif
/*
* svc_raw.c, This a toy for simple testing and timing.
@@ -39,130 +47,214 @@ static char *rcsid = "$FreeBSD$";
* This lets us similate rpc and get rpc (round trip) overhead, without
* any interference from the kernal.
*
- * Copyright (C) 1984, Sun Microsystems, Inc.
*/
+#include "reentrant.h"
+#include "namespace.h"
#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <rpc/raw.h>
#include <stdlib.h>
+#include "un-namespace.h"
+
+#ifndef UDPMSGSIZE
+#define UDPMSGSIZE 8800
+#endif
/*
* This is the "network" that we will be moving data over
*/
-static struct svcraw_private {
- char _raw_buf[UDPMSGSIZE];
+static struct svc_raw_private {
+ char *raw_buf; /* should be shared with the cl handle */
SVCXPRT server;
XDR xdr_stream;
char verf_body[MAX_AUTH_BYTES];
-} *svcraw_private;
-
-static bool_t svcraw_recv();
-static enum xprt_stat svcraw_stat();
-static bool_t svcraw_getargs();
-static bool_t svcraw_reply();
-static bool_t svcraw_freeargs();
-static void svcraw_destroy();
-
-static struct xp_ops server_ops = {
- svcraw_recv,
- svcraw_stat,
- svcraw_getargs,
- svcraw_reply,
- svcraw_freeargs,
- svcraw_destroy
-};
+} *svc_raw_private;
+
+extern mutex_t svcraw_lock;
+
+static enum xprt_stat svc_raw_stat __P((SVCXPRT *));
+static bool_t svc_raw_recv __P((SVCXPRT *, struct rpc_msg *));
+static bool_t svc_raw_reply __P((SVCXPRT *, struct rpc_msg *));
+static bool_t svc_raw_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static bool_t svc_raw_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static void svc_raw_destroy __P((SVCXPRT *));
+static void svc_raw_ops __P((SVCXPRT *));
+static bool_t svc_raw_control __P((SVCXPRT *, const u_int, void *));
+
+char *__rpc_rawcombuf = NULL;
SVCXPRT *
-svcraw_create()
+svc_raw_create()
{
- register struct svcraw_private *srp = svcraw_private;
+ struct svc_raw_private *srp;
+/* VARIABLES PROTECTED BY svcraw_lock: svc_raw_private, srp */
- if (srp == 0) {
- srp = (struct svcraw_private *)calloc(1, sizeof (*srp));
- if (srp == 0)
- return (0);
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ srp = (struct svc_raw_private *)calloc(1, sizeof (*srp));
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (NULL);
+ }
+ if (__rpc_rawcombuf == NULL)
+ __rpc_rawcombuf = calloc(UDPMSGSIZE, sizeof (char));
+ srp->raw_buf = __rpc_rawcombuf; /* Share it with the client */
+ svc_raw_private = srp;
}
- srp->server.xp_sock = 0;
+ srp->server.xp_fd = FD_SETSIZE;
srp->server.xp_port = 0;
- srp->server.xp_ops = &server_ops;
+ srp->server.xp_p3 = NULL;
+ svc_raw_ops(&srp->server);
srp->server.xp_verf.oa_base = srp->verf_body;
- xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+ xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE);
+ xprt_register(&srp->server);
+ mutex_unlock(&svcraw_lock);
return (&srp->server);
}
+/*ARGSUSED*/
static enum xprt_stat
-svcraw_stat()
+svc_raw_stat(xprt)
+SVCXPRT *xprt; /* args needed to satisfy ANSI-C typechecking */
{
-
return (XPRT_IDLE);
}
+/*ARGSUSED*/
static bool_t
-svcraw_recv(xprt, msg)
+svc_raw_recv(xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
- register struct svcraw_private *srp = svcraw_private;
- register XDR *xdrs;
+ struct svc_raw_private *srp;
+ XDR *xdrs;
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
- if (srp == 0)
- return (0);
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_DECODE;
- XDR_SETPOS(xdrs, 0);
- if (! xdr_callmsg(xdrs, msg))
- return (FALSE);
+ (void) XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg)) {
+ return (FALSE);
+ }
return (TRUE);
}
+/*ARGSUSED*/
static bool_t
-svcraw_reply(xprt, msg)
+svc_raw_reply(xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
- register struct svcraw_private *srp = svcraw_private;
- register XDR *xdrs;
+ struct svc_raw_private *srp;
+ XDR *xdrs;
- if (srp == 0)
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_ENCODE;
- XDR_SETPOS(xdrs, 0);
- if (! xdr_replymsg(xdrs, msg))
- return (FALSE);
- (void)XDR_GETPOS(xdrs); /* called just for overhead */
+ (void) XDR_SETPOS(xdrs, 0);
+ if (! xdr_replymsg(xdrs, msg)) {
+ return (FALSE);
+ }
+ (void) XDR_GETPOS(xdrs); /* called just for overhead */
return (TRUE);
}
+/*ARGSUSED*/
static bool_t
-svcraw_getargs(xprt, xdr_args, args_ptr)
+svc_raw_getargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
- register struct svcraw_private *srp = svcraw_private;
+ struct svc_raw_private *srp;
- if (srp == 0)
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
return (FALSE);
- return ((*xdr_args)(&srp->xdr_stream, args_ptr));
+ }
+ mutex_unlock(&svcraw_lock);
+ return (*xdr_args)(&srp->xdr_stream, args_ptr);
}
+/*ARGSUSED*/
static bool_t
-svcraw_freeargs(xprt, xdr_args, args_ptr)
+svc_raw_freeargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
- register struct svcraw_private *srp = svcraw_private;
- register XDR *xdrs;
+ struct svc_raw_private *srp;
+ XDR *xdrs;
- if (srp == 0)
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_FREE;
- return ((*xdr_args)(xdrs, args_ptr));
+ return (*xdr_args)(xdrs, args_ptr);
+}
+
+/*ARGSUSED*/
+static void
+svc_raw_destroy(xprt)
+SVCXPRT *xprt;
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
}
static void
-svcraw_destroy()
+svc_raw_ops(xprt)
+ SVCXPRT *xprt;
{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+ extern mutex_t ops_lock;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_raw_recv;
+ ops.xp_stat = svc_raw_stat;
+ ops.xp_getargs = svc_raw_getargs;
+ ops.xp_reply = svc_raw_reply;
+ ops.xp_freeargs = svc_raw_freeargs;
+ ops.xp_destroy = svc_raw_destroy;
+ ops2.xp_control = svc_raw_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
}
diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c
index bc5b48a7d0dd..78862fe0410d 100644
--- a/lib/libc/rpc/svc_run.c
+++ b/lib/libc/rpc/svc_run.c
@@ -1,3 +1,5 @@
+/* $NetBSD: svc_run.c,v 1.17 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/
@@ -37,53 +40,54 @@ static char *rcsid = "$FreeBSD$";
* This is the rpc server side idle loop
* Wait for input, call server program.
*/
+#include "reentrant.h"
#include "namespace.h"
+#include <err.h>
+#include <errno.h>
#include <rpc/rpc.h>
#include <stdio.h>
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "un-namespace.h"
-extern int __svc_fdsetsize;
-extern fd_set *__svc_fdset;
+#include <rpc/rpc.h>
void
svc_run()
{
- fd_set *fds;
+ fd_set readfds;
+ extern rwlock_t svc_fd_lock;
for (;;) {
- if (__svc_fdset) {
- int bytes = howmany(__svc_fdsetsize, NFDBITS) *
- sizeof(fd_mask);
- fds = (fd_set *)malloc(bytes);
- memcpy(fds, __svc_fdset, bytes);
- } else
- fds = NULL;
- switch (_select(svc_maxfd + 1, fds, NULL, NULL,
- (struct timeval *)0)) {
+ rwlock_rdlock(&svc_fd_lock);
+ readfds = svc_fdset;
+ rwlock_unlock(&svc_fd_lock);
+ switch (_select(svc_maxfd+1, &readfds, NULL, NULL, NULL)) {
case -1:
+ FD_ZERO(&readfds);
if (errno == EINTR) {
- if (fds)
- free(fds);
continue;
}
- perror("svc_run: - select failed");
- if (fds)
- free(fds);
+ warn("svc_run: - select failed");
return;
case 0:
- if (fds)
- free(fds);
continue;
default:
- /* if fds == NULL, _select() can't return a result */
- svc_getreqset2(fds, svc_maxfd + 1);
- free(fds);
+ svc_getreqset(&readfds);
}
}
}
+
+/*
+ * This function causes svc_run() to exit by telling it that it has no
+ * more work to do.
+ */
+void
+svc_exit()
+{
+ extern rwlock_t svc_fd_lock;
+
+ rwlock_wrlock(&svc_fd_lock);
+ FD_ZERO(&svc_fdset);
+ rwlock_unlock(&svc_fd_lock);
+}
diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c
index 1bfaf1c8cd45..fec87b7fcf29 100644
--- a/lib/libc/rpc/svc_simple.c
+++ b/lib/libc/rpc/svc_simple.c
@@ -1,3 +1,6 @@
+/* $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ */
+/* $FreeBSD$ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,125 +29,279 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
+/* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */
/*
* svc_simple.c
* Simplified front end to rpc.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
*/
+/*
+ * This interface creates a virtual listener for all the services
+ * started thru rpc_reg(). It listens on the same endpoint for
+ * all the services and then executes the corresponding service
+ * for the given prognum and procnum.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <sys/socket.h>
-#include <netdb.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+static void universal __P((struct svc_req *, SVCXPRT *));
static struct proglst {
- char *(*p_progname)();
- int p_prognum;
- int p_procnum;
+ char *(*p_progname) __P((char *));
+ rpcprog_t p_prognum;
+ rpcvers_t p_versnum;
+ rpcproc_t p_procnum;
+ SVCXPRT *p_transp;
+ char *p_netid;
+ char *p_xdrbuf;
+ int p_recvsz;
xdrproc_t p_inproc, p_outproc;
struct proglst *p_nxt;
} *proglst;
-static void universal();
-static SVCXPRT *transp;
-struct proglst *pl;
+
+static const char rpc_reg_err[] = "%s: %s";
+static const char rpc_reg_msg[] = "rpc_reg: ";
+static const char __reg_err1[] = "can't find appropriate transport";
+static const char __reg_err2[] = "can't get protocol info";
+static const char __reg_err3[] = "unsupported transport size";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * For simplified, easy to use kind of rpc interfaces.
+ * nettype indicates the type of transport on which the service will be
+ * listening. Used for conservation of the system resource. Only one
+ * handle is created for all the services (actually one of each netid)
+ * and same xdrbuf is used for same netid. The size of the arguments
+ * is also limited by the recvsize for that transport, even if it is
+ * a COTS transport. This may be wrong, but for cases like these, they
+ * should not use the simplified interfaces like this.
+ */
int
-registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
- int prognum, versnum, procnum;
- char *(*progname)();
- xdrproc_t inproc, outproc;
+rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype)
+ rpcprog_t prognum; /* program number */
+ rpcvers_t versnum; /* version number */
+ rpcproc_t procnum; /* procedure number */
+ char *(*progname) __P((char *)); /* Server routine */
+ xdrproc_t inproc, outproc; /* in/out XDR procedures */
+ char *nettype; /* nettype */
{
+ struct netconfig *nconf;
+ int done = FALSE;
+ void *handle;
+ extern mutex_t proglst_lock;
+
+
if (procnum == NULLPROC) {
- (void) fprintf(stderr,
- "can't reassign procedure number %ld\n", NULLPROC);
+ warnx("%s can't reassign procedure number %u", rpc_reg_msg,
+ NULLPROC);
return (-1);
}
- if (transp == 0) {
- transp = svcudp_create(RPC_ANYSOCK);
- if (transp == NULL) {
- (void) fprintf(stderr, "couldn't create an rpc server\n");
- return (-1);
- }
- }
- (void) pmap_unset((u_long)prognum, (u_long)versnum);
- if (!svc_register(transp, (u_long)prognum, (u_long)versnum,
- universal, IPPROTO_UDP)) {
- (void) fprintf(stderr, "couldn't register prog %d vers %d\n",
- prognum, versnum);
+
+ if (nettype == NULL)
+ nettype = "netpath"; /* The default behavior */
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err1);
return (-1);
}
- pl = (struct proglst *)malloc(sizeof(struct proglst));
- if (pl == NULL) {
- (void) fprintf(stderr, "registerrpc: out of memory\n");
+/* VARIABLES PROTECTED BY proglst_lock: proglst */
+ mutex_lock(&proglst_lock);
+ while ((nconf = __rpc_getconf(handle)) != NULL) {
+ struct proglst *pl;
+ SVCXPRT *svcxprt;
+ int madenow;
+ u_int recvsz;
+ char *xdrbuf;
+ char *netid;
+
+ madenow = FALSE;
+ svcxprt = NULL;
+ for (pl = proglst; pl; pl = pl->p_nxt)
+ if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
+ svcxprt = pl->p_transp;
+ xdrbuf = pl->p_xdrbuf;
+ recvsz = pl->p_recvsz;
+ netid = pl->p_netid;
+ break;
+ }
+
+ if (svcxprt == NULL) {
+ struct __rpc_sockinfo si;
+
+ svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+ if (svcxprt == NULL)
+ continue;
+ if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err2);
+ SVC_DESTROY(svcxprt);
+ continue;
+ }
+ recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0);
+ if (recvsz == 0) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err3);
+ SVC_DESTROY(svcxprt);
+ continue;
+ }
+ if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
+ ((netid = strdup(nconf->nc_netid)) == NULL)) {
+ warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+ SVC_DESTROY(svcxprt);
+ break;
+ }
+ madenow = TRUE;
+ }
+ /*
+ * Check if this (program, version, netid) had already been
+ * registered. The check may save a few RPC calls to rpcbind
+ */
+ for (pl = proglst; pl; pl = pl->p_nxt)
+ if ((pl->p_prognum == prognum) &&
+ (pl->p_versnum == versnum) &&
+ (strcmp(pl->p_netid, netid) == 0))
+ break;
+ if (pl == NULL) { /* Not yet */
+ (void) rpcb_unset(prognum, versnum, nconf);
+ } else {
+ /* so that svc_reg does not call rpcb_set() */
+ nconf = NULL;
+ }
+
+ if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
+ warnx("%s couldn't register prog %u vers %u for %s",
+ rpc_reg_msg, (unsigned)prognum,
+ (unsigned)versnum, netid);
+ if (madenow) {
+ SVC_DESTROY(svcxprt);
+ free(xdrbuf);
+ free(netid);
+ }
+ continue;
+ }
+
+ pl = malloc(sizeof (struct proglst));
+ if (pl == NULL) {
+ warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+ if (madenow) {
+ SVC_DESTROY(svcxprt);
+ free(xdrbuf);
+ free(netid);
+ }
+ break;
+ }
+ pl->p_progname = progname;
+ pl->p_prognum = prognum;
+ pl->p_versnum = versnum;
+ pl->p_procnum = procnum;
+ pl->p_inproc = inproc;
+ pl->p_outproc = outproc;
+ pl->p_transp = svcxprt;
+ pl->p_xdrbuf = xdrbuf;
+ pl->p_recvsz = recvsz;
+ pl->p_netid = netid;
+ pl->p_nxt = proglst;
+ proglst = pl;
+ done = TRUE;
+ }
+ __rpc_endconf(handle);
+ mutex_unlock(&proglst_lock);
+
+ if (done == FALSE) {
+ warnx("%s cant find suitable transport for %s",
+ rpc_reg_msg, nettype);
return (-1);
}
- pl->p_progname = progname;
- pl->p_prognum = prognum;
- pl->p_procnum = procnum;
- pl->p_inproc = inproc;
- pl->p_outproc = outproc;
- pl->p_nxt = proglst;
- proglst = pl;
return (0);
}
+/*
+ * The universal handler for the services registered using registerrpc.
+ * It handles both the connectionless and the connection oriented cases.
+ */
+
static void
universal(rqstp, transp)
struct svc_req *rqstp;
SVCXPRT *transp;
{
- int prog, proc;
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc;
char *outdata;
- char xdrbuf[UDPMSGSIZE];
+ char *xdrbuf;
struct proglst *pl;
+ extern mutex_t proglst_lock;
/*
* enforce "procnum 0 is echo" convention
*/
if (rqstp->rq_proc == NULLPROC) {
- if (svc_sendreply(transp, xdr_void, NULL) == FALSE) {
- (void) fprintf(stderr, "xxx\n");
- exit(1);
+ if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) ==
+ FALSE) {
+ warnx("svc_sendreply failed");
}
return;
}
prog = rqstp->rq_prog;
+ vers = rqstp->rq_vers;
proc = rqstp->rq_proc;
- for (pl = proglst; pl != NULL; pl = pl->p_nxt)
- if (pl->p_prognum == prog && pl->p_procnum == proc) {
+ mutex_lock(&proglst_lock);
+ for (pl = proglst; pl; pl = pl->p_nxt)
+ if (pl->p_prognum == prog && pl->p_procnum == proc &&
+ pl->p_versnum == vers &&
+ (strcmp(pl->p_netid, transp->xp_netid) == 0)) {
/* decode arguments into a CLEAN buffer */
- memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */
+ xdrbuf = pl->p_xdrbuf;
+ /* Zero the arguments: reqd ! */
+ (void) memset(xdrbuf, 0, sizeof (pl->p_recvsz));
+ /*
+ * Assuming that sizeof (xdrbuf) would be enough
+ * for the arguments; if not then the program
+ * may bomb. BEWARE!
+ */
if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
svcerr_decode(transp);
+ mutex_unlock(&proglst_lock);
return;
}
outdata = (*(pl->p_progname))(xdrbuf);
- if (outdata == NULL && pl->p_outproc != xdr_void)
+ if (outdata == NULL &&
+ pl->p_outproc != (xdrproc_t) xdr_void){
/* there was an error */
+ mutex_unlock(&proglst_lock);
return;
+ }
if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
- (void) fprintf(stderr,
- "trouble replying to prog %d\n",
- pl->p_prognum);
- exit(1);
+ warnx(
+ "rpc: rpc_reg trouble replying to prog %u vers %u",
+ (unsigned)prog, (unsigned)vers);
+ mutex_unlock(&proglst_lock);
+ return;
}
/* free the decoded arguments */
(void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+ mutex_unlock(&proglst_lock);
return;
}
- (void) fprintf(stderr, "never registered prog %d\n", prog);
- exit(1);
+ mutex_unlock(&proglst_lock);
+ /* This should never happen */
+ warnx("rpc: rpc_reg: never registered prog %u vers %u",
+ (unsigned)prog, (unsigned)vers);
+ return;
}
-
diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c
deleted file mode 100644
index d7e425bf247d..000000000000
--- a/lib/libc/rpc/svc_tcp.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * svc_tcp.c, Server side for TCP/IP based RPC.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- *
- * Actually implements two flavors of transporter -
- * a tcp rendezvouser (a listner and connection establisher)
- * and a record/tcp stream.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include "un-namespace.h"
-
-/*
- * Ops vector for TCP/IP based rpc service handle
- */
-static bool_t svctcp_recv();
-static enum xprt_stat svctcp_stat();
-static bool_t svctcp_getargs();
-static bool_t svctcp_reply();
-static bool_t svctcp_freeargs();
-static void svctcp_destroy();
-
-static struct xp_ops svctcp_op = {
- svctcp_recv,
- svctcp_stat,
- svctcp_getargs,
- svctcp_reply,
- svctcp_freeargs,
- svctcp_destroy
-};
-
-/*
- * Ops vector for TCP/IP rendezvous handler
- */
-static bool_t rendezvous_request();
-static enum xprt_stat rendezvous_stat();
-
-static struct xp_ops svctcp_rendezvous_op = {
- rendezvous_request,
- rendezvous_stat,
- (bool_t (*)())abort,
- (bool_t (*)())abort,
- (bool_t (*)())abort,
- svctcp_destroy
-};
-
-static int readtcp(), writetcp();
-static SVCXPRT *makefd_xprt();
-
-struct tcp_rendezvous { /* kept in xprt->xp_p1 */
- u_int sendsize;
- u_int recvsize;
-};
-
-struct tcp_conn { /* kept in xprt->xp_p1 */
- enum xprt_stat strm_stat;
- u_long x_id;
- XDR xdrs;
- char verf_body[MAX_AUTH_BYTES];
-};
-
-/*
- * Usage:
- * xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
- *
- * Creates, registers, and returns a (rpc) tcp based transporter.
- * Once *xprt is initialized, it is registered as a transporter
- * see (svc.h, xprt_register). This routine returns
- * a NULL if a problem occurred.
- *
- * If sock<0 then a socket is created, else sock is used.
- * If the socket, sock is not bound to a port then svctcp_create
- * binds it to an arbitrary port. The routine then starts a tcp
- * listener on the socket's associated port. In any (successful) case,
- * xprt->xp_sock is the registered socket number and xprt->xp_port is the
- * associated port number.
- *
- * Since tcp streams do buffered io similar to stdio, the caller can specify
- * how big the send and receive buffers are via the second and third parms;
- * 0 => use the system default.
- */
-SVCXPRT *
-svctcp_create(sock, sendsize, recvsize)
- register int sock;
- u_int sendsize;
- u_int recvsize;
-{
- bool_t madesock = FALSE;
- register SVCXPRT *xprt;
- register struct tcp_rendezvous *r;
- struct sockaddr_in addr;
- int len = sizeof(struct sockaddr_in);
- int on;
-
- if (sock == RPC_ANYSOCK) {
- if ((sock = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- perror("svctcp_.c - udp socket creation problem");
- return ((SVCXPRT *)NULL);
- }
- madesock = TRUE;
- }
- on = 1;
- if (_ioctl(sock, FIONBIO, &on) < 0) {
- perror("svc_tcp.c - cannot turn on non-blocking mode");
- if (madesock)
- (void)_close(sock);
- return ((SVCXPRT *)NULL);
- }
- memset(&addr, 0, sizeof (addr));
- addr.sin_len = sizeof(struct sockaddr_in);
- addr.sin_family = AF_INET;
- if (bindresvport(sock, &addr)) {
- addr.sin_port = 0;
- (void)_bind(sock, (struct sockaddr *)&addr, len);
- }
- if ((_getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
- (_listen(sock, 2) != 0)) {
- perror("svctcp_.c - cannot getsockname or listen");
- if (madesock)
- (void)_close(sock);
- return ((SVCXPRT *)NULL);
- }
- r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
- if (r == NULL) {
- (void) fprintf(stderr, "svctcp_create: out of memory\n");
- return (NULL);
- }
- r->sendsize = sendsize;
- r->recvsize = recvsize;
- xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
- if (xprt == NULL) {
- (void) fprintf(stderr, "svctcp_create: out of memory\n");
- return (NULL);
- }
- xprt->xp_p2 = NULL;
- xprt->xp_p1 = (caddr_t)r;
- xprt->xp_verf = _null_auth;
- xprt->xp_ops = &svctcp_rendezvous_op;
- xprt->xp_port = ntohs(addr.sin_port);
- xprt->xp_sock = sock;
- xprt_register(xprt);
- return (xprt);
-}
-
-/*
- * Like svtcp_create(), except the routine takes any *open* UNIX file
- * descriptor as its first input.
- */
-SVCXPRT *
-svcfd_create(fd, sendsize, recvsize)
- int fd;
- u_int sendsize;
- u_int recvsize;
-{
-
- return (makefd_xprt(fd, sendsize, recvsize));
-}
-
-static SVCXPRT *
-makefd_xprt(fd, sendsize, recvsize)
- int fd;
- u_int sendsize;
- u_int recvsize;
-{
- register SVCXPRT *xprt;
- register struct tcp_conn *cd;
-
- xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
- if (xprt == (SVCXPRT *)NULL) {
- (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
- goto done;
- }
- cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
- if (cd == (struct tcp_conn *)NULL) {
- (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
- mem_free((char *) xprt, sizeof(SVCXPRT));
- xprt = (SVCXPRT *)NULL;
- goto done;
- }
- cd->strm_stat = XPRT_IDLE;
- xdrrec_create(&(cd->xdrs), sendsize, recvsize,
- (caddr_t)xprt, readtcp, writetcp);
- xprt->xp_p2 = NULL;
- xprt->xp_p1 = (caddr_t)cd;
- xprt->xp_verf.oa_base = cd->verf_body;
- xprt->xp_addrlen = 0;
- xprt->xp_ops = &svctcp_op; /* truely deals with calls */
- xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
- xprt->xp_sock = fd;
- xprt_register(xprt);
- done:
- return (xprt);
-}
-
-static bool_t
-rendezvous_request(xprt)
- register SVCXPRT *xprt;
-{
- int sock;
- struct tcp_rendezvous *r;
- struct sockaddr_in addr;
- int len;
- int off;
-
- r = (struct tcp_rendezvous *)xprt->xp_p1;
- again:
- len = sizeof(struct sockaddr_in);
- if ((sock = _accept(xprt->xp_sock, (struct sockaddr *)&addr,
- &len)) < 0) {
- if (errno == EINTR)
- goto again;
- return (FALSE);
- }
- /*
- * Guard against FTP bounce attacks.
- */
- if (addr.sin_port == htons(20)) {
- _close(sock);
- return (FALSE);
- }
- /*
- * The listening socket is in FIONBIO mode and we inherit it.
- */
- off = 0;
- if (_ioctl(sock, FIONBIO, &off) < 0) {
- _close(sock);
- return (FALSE);
- }
- /*
- * make a new transporter (re-uses xprt)
- */
- xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
- xprt->xp_raddr = addr;
- xprt->xp_addrlen = len;
- return (FALSE); /* there is never an rpc msg to be processed */
-}
-
-static enum xprt_stat
-rendezvous_stat()
-{
-
- return (XPRT_IDLE);
-}
-
-static void
-svctcp_destroy(xprt)
- register SVCXPRT *xprt;
-{
- register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
-
- xprt_unregister(xprt);
- (void)_close(xprt->xp_sock);
- if (xprt->xp_port != 0) {
- /* a rendezvouser socket */
- xprt->xp_port = 0;
- } else {
- /* an actual connection socket */
- XDR_DESTROY(&(cd->xdrs));
- }
- mem_free((caddr_t)cd, sizeof(struct tcp_conn));
- mem_free((caddr_t)xprt, sizeof(SVCXPRT));
-}
-
-/*
- * All read operations timeout after 35 seconds.
- * A timeout is fatal for the connection.
- */
-static struct timeval wait_per_try = { 35, 0 };
-
-/*
- * reads data from the tcp conection.
- * any error is fatal and the connection is closed.
- * (And a read of zero bytes is a half closed stream => error.)
- *
- * Note: we have to be careful here not to allow ourselves to become
- * blocked too long in this routine. While we're waiting for data from one
- * client, another client may be trying to connect. To avoid this situation,
- * some code from svc_run() is transplanted here: the _select() loop checks
- * all RPC descriptors including the one we want and calls svc_getreqset2()
- * to handle new requests if any are detected.
- */
-static int
-readtcp(xprt, buf, len)
- register SVCXPRT *xprt;
- caddr_t buf;
- register int len;
-{
- register int sock = xprt->xp_sock;
- struct timeval start, delta, tv;
- struct timeval tmp1, tmp2;
- fd_set *fds;
- extern fd_set *__svc_fdset;
- extern int __svc_fdsetsize;
-
- delta = wait_per_try;
- fds = NULL;
- gettimeofday(&start, NULL);
- do {
- int bytes = howmany(__svc_fdsetsize, NFDBITS) *
- sizeof(fd_mask);
- if (fds != NULL)
- free(fds);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL)
- goto fatal_err;
- memcpy(fds, __svc_fdset, bytes);
-
- /* XXX we know the other bits are still clear */
- FD_SET(sock, fds);
- tv = delta; /* in case _select() implements writeback */
- switch (_select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
- case -1:
- FD_ZERO(fds);
- if (errno != EINTR)
- goto fatal_err;
- gettimeofday(&tmp1, NULL);
- timersub(&tmp1, &start, &tmp2);
- timersub(&wait_per_try, &tmp2, &tmp1);
- if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
- goto fatal_err;
- delta = tmp1;
- continue;
- case 0:
- goto fatal_err;
- default:
- if (!FD_ISSET(sock, fds)) {
- svc_getreqset2(fds, svc_maxfd + 1);
- gettimeofday(&tmp1, NULL);
- timersub(&tmp1, &start, &tmp2);
- timersub(&wait_per_try, &tmp2, &tmp1);
- if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
- goto fatal_err;
- delta = tmp1;
- continue;
- }
- }
- } while (!FD_ISSET(sock, fds));
- if ((len = _read(sock, buf, len)) > 0) {
- if (fds != NULL)
- free(fds);
- return (len);
- }
-fatal_err:
- ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
- if (fds != NULL)
- free(fds);
- return (-1);
-}
-
-/*
- * writes data to the tcp connection.
- * Any error is fatal and the connection is closed.
- */
-static int
-writetcp(xprt, buf, len)
- register SVCXPRT *xprt;
- caddr_t buf;
- int len;
-{
- register int i, cnt;
-
- for (cnt = len; cnt > 0; cnt -= i, buf += i) {
- if ((i = _write(xprt->xp_sock, buf, cnt)) < 0) {
- ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
- XPRT_DIED;
- return (-1);
- }
- }
- return (len);
-}
-
-static enum xprt_stat
-svctcp_stat(xprt)
- SVCXPRT *xprt;
-{
- register struct tcp_conn *cd =
- (struct tcp_conn *)(xprt->xp_p1);
-
- if (cd->strm_stat == XPRT_DIED)
- return (XPRT_DIED);
- if (! xdrrec_eof(&(cd->xdrs)))
- return (XPRT_MOREREQS);
- return (XPRT_IDLE);
-}
-
-static bool_t
-svctcp_recv(xprt, msg)
- SVCXPRT *xprt;
- register struct rpc_msg *msg;
-{
- register struct tcp_conn *cd =
- (struct tcp_conn *)(xprt->xp_p1);
- register XDR *xdrs = &(cd->xdrs);
-
- xdrs->x_op = XDR_DECODE;
- (void)xdrrec_skiprecord(xdrs);
- if (xdr_callmsg(xdrs, msg)) {
- cd->x_id = msg->rm_xid;
- return (TRUE);
- }
- cd->strm_stat = XPRT_DIED; /* XXXX */
- return (FALSE);
-}
-
-static bool_t
-svctcp_getargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
-
- return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
-}
-
-static bool_t
-svctcp_freeargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
- register XDR *xdrs =
- &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_args)(xdrs, args_ptr));
-}
-
-static bool_t
-svctcp_reply(xprt, msg)
- SVCXPRT *xprt;
- register struct rpc_msg *msg;
-{
- register struct tcp_conn *cd =
- (struct tcp_conn *)(xprt->xp_p1);
- register XDR *xdrs = &(cd->xdrs);
- register bool_t stat;
-
- xdrs->x_op = XDR_ENCODE;
- msg->rm_xid = cd->x_id;
- stat = xdr_replymsg(xdrs, msg);
- (void)xdrrec_endofrecord(xdrs, TRUE);
- return (stat);
-}
diff --git a/lib/libc/rpc/svc_udp.c b/lib/libc/rpc/svc_udp.c
deleted file mode 100644
index 0abd48696bdb..000000000000
--- a/lib/libc/rpc/svc_udp.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * svc_udp.c,
- * Server side for UDP/IP based RPC. (Does some caching in the hopes of
- * achieving execute-at-most-once semantics.)
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include "un-namespace.h"
-
-#define rpc_buffer(xprt) ((xprt)->xp_p1)
-#define MAX(a, b) ((a > b) ? a : b)
-
-static bool_t svcudp_recv();
-static bool_t svcudp_reply();
-static enum xprt_stat svcudp_stat();
-static bool_t svcudp_getargs();
-static bool_t svcudp_freeargs();
-static void svcudp_destroy();
-static void cache_set __P((SVCXPRT *, u_long));
-static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, u_long *));
-
-static struct xp_ops svcudp_op = {
- svcudp_recv,
- svcudp_stat,
- svcudp_getargs,
- svcudp_reply,
- svcudp_freeargs,
- svcudp_destroy
-};
-
-/*
- * kept in xprt->xp_p2
- */
-struct svcudp_data {
- u_int su_iosz; /* byte size of send.recv buffer */
- u_long su_xid; /* transaction id */
- XDR su_xdrs; /* XDR handle */
- char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
- char * su_cache; /* cached data, NULL if no cache */
-};
-#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
-
-/*
- * Usage:
- * xprt = svcudp_create(sock);
- *
- * If sock<0 then a socket is created, else sock is used.
- * If the socket, sock is not bound to a port then svcudp_create
- * binds it to an arbitrary port. In any (successful) case,
- * xprt->xp_sock is the registered socket number and xprt->xp_port is the
- * associated port number.
- * Once *xprt is initialized, it is registered as a transporter;
- * see (svc.h, xprt_register).
- * The routines returns NULL if a problem occurred.
- */
-SVCXPRT *
-svcudp_bufcreate(sock, sendsz, recvsz)
- register int sock;
- u_int sendsz, recvsz;
-{
- bool_t madesock = FALSE;
- register SVCXPRT *xprt;
- register struct svcudp_data *su;
- struct sockaddr_in addr;
- int len = sizeof(struct sockaddr_in);
-
- if (sock == RPC_ANYSOCK) {
- if ((sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- perror("svcudp_create: socket creation problem");
- return ((SVCXPRT *)NULL);
- }
- madesock = TRUE;
- }
- memset((char *)&addr, 0, sizeof (addr));
- addr.sin_len = sizeof(struct sockaddr_in);
- addr.sin_family = AF_INET;
- if (bindresvport(sock, &addr)) {
- addr.sin_port = 0;
- (void)_bind(sock, (struct sockaddr *)&addr, len);
- }
- if (_getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
- perror("svcudp_create - cannot getsockname");
- if (madesock)
- (void)_close(sock);
- return ((SVCXPRT *)NULL);
- }
- xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
- if (xprt == NULL) {
- (void)fprintf(stderr, "svcudp_create: out of memory\n");
- return (NULL);
- }
- su = (struct svcudp_data *)mem_alloc(sizeof(*su));
- if (su == NULL) {
- (void)fprintf(stderr, "svcudp_create: out of memory\n");
- return (NULL);
- }
- su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
- if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
- (void)fprintf(stderr, "svcudp_create: out of memory\n");
- return (NULL);
- }
- xdrmem_create(
- &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
- su->su_cache = NULL;
- xprt->xp_p2 = (caddr_t)su;
- xprt->xp_verf.oa_base = su->su_verfbody;
- xprt->xp_ops = &svcudp_op;
- xprt->xp_port = ntohs(addr.sin_port);
- xprt->xp_sock = sock;
- xprt_register(xprt);
- return (xprt);
-}
-
-SVCXPRT *
-svcudp_create(sock)
- int sock;
-{
-
- return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
-}
-
-static enum xprt_stat
-svcudp_stat(xprt)
- SVCXPRT *xprt;
-{
-
- return (XPRT_IDLE);
-}
-
-static bool_t
-svcudp_recv(xprt, msg)
- register SVCXPRT *xprt;
- struct rpc_msg *msg;
-{
- register struct svcudp_data *su = su_data(xprt);
- register XDR *xdrs = &(su->su_xdrs);
- register int rlen;
- char *reply;
- u_long replylen;
-
- again:
- xprt->xp_addrlen = sizeof(struct sockaddr_in);
- rlen = _recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
- 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
- if (rlen == -1 && errno == EINTR)
- goto again;
- if (rlen == -1 || rlen < 4*sizeof(u_int32_t))
- return (FALSE);
- xdrs->x_op = XDR_DECODE;
- XDR_SETPOS(xdrs, 0);
- if (! xdr_callmsg(xdrs, msg))
- return (FALSE);
- su->su_xid = msg->rm_xid;
- if (su->su_cache != NULL) {
- if (cache_get(xprt, msg, &reply, &replylen)) {
- (void) _sendto(xprt->xp_sock, reply, (int) replylen, 0,
- (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
- return (TRUE);
- }
- }
- return (TRUE);
-}
-
-static bool_t
-svcudp_reply(xprt, msg)
- register SVCXPRT *xprt;
- struct rpc_msg *msg;
-{
- register struct svcudp_data *su = su_data(xprt);
- register XDR *xdrs = &(su->su_xdrs);
- register int slen;
- register bool_t stat = FALSE;
-
- xdrs->x_op = XDR_ENCODE;
- XDR_SETPOS(xdrs, 0);
- msg->rm_xid = su->su_xid;
- if (xdr_replymsg(xdrs, msg)) {
- slen = (int)XDR_GETPOS(xdrs);
- if (_sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
- (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
- == slen) {
- stat = TRUE;
- if (su->su_cache && slen >= 0) {
- cache_set(xprt, (u_long) slen);
- }
- }
- }
- return (stat);
-}
-
-static bool_t
-svcudp_getargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
-
- return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
-}
-
-static bool_t
-svcudp_freeargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
- register XDR *xdrs = &(su_data(xprt)->su_xdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_args)(xdrs, args_ptr));
-}
-
-static void
-svcudp_destroy(xprt)
- register SVCXPRT *xprt;
-{
- register struct svcudp_data *su = su_data(xprt);
-
- xprt_unregister(xprt);
- (void)_close(xprt->xp_sock);
- XDR_DESTROY(&(su->su_xdrs));
- mem_free(rpc_buffer(xprt), su->su_iosz);
- mem_free((caddr_t)su, sizeof(struct svcudp_data));
- mem_free((caddr_t)xprt, sizeof(SVCXPRT));
-}
-
-
-/***********this could be a separate file*********************/
-
-/*
- * Fifo cache for udp server
- * Copies pointers to reply buffers into fifo cache
- * Buffers are sent again if retransmissions are detected.
- */
-
-#define SPARSENESS 4 /* 75% sparse */
-
-#define CACHE_PERROR(msg) \
- (void) fprintf(stderr,"%s\n", msg)
-
-#define ALLOC(type, size) \
- (type *) mem_alloc((unsigned) (sizeof(type) * (size)))
-
-#define BZERO(addr, type, size) \
- memset((char *) addr, 0, sizeof(type) * (int) (size))
-
-/*
- * An entry in the cache
- */
-typedef struct cache_node *cache_ptr;
-struct cache_node {
- /*
- * Index into cache is xid, proc, vers, prog and address
- */
- u_long cache_xid;
- u_long cache_proc;
- u_long cache_vers;
- u_long cache_prog;
- struct sockaddr_in cache_addr;
- /*
- * The cached reply and length
- */
- char * cache_reply;
- u_long cache_replylen;
- /*
- * Next node on the list, if there is a collision
- */
- cache_ptr cache_next;
-};
-
-
-
-/*
- * The entire cache
- */
-struct udp_cache {
- u_long uc_size; /* size of cache */
- cache_ptr *uc_entries; /* hash table of entries in cache */
- cache_ptr *uc_fifo; /* fifo list of entries in cache */
- u_long uc_nextvictim; /* points to next victim in fifo list */
- u_long uc_prog; /* saved program number */
- u_long uc_vers; /* saved version number */
- u_long uc_proc; /* saved procedure number */
- struct sockaddr_in uc_addr; /* saved caller's address */
-};
-
-
-/*
- * the hashing function
- */
-#define CACHE_LOC(transp, xid) \
- (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
-
-
-/*
- * Enable use of the cache.
- * Note: there is no disable.
- */
-int svcudp_enablecache(transp, size)
- SVCXPRT *transp;
- u_long size;
-{
- struct svcudp_data *su = su_data(transp);
- struct udp_cache *uc;
-
- if (su->su_cache != NULL) {
- CACHE_PERROR("enablecache: cache already enabled");
- return(0);
- }
- uc = ALLOC(struct udp_cache, 1);
- if (uc == NULL) {
- CACHE_PERROR("enablecache: could not allocate cache");
- return(0);
- }
- uc->uc_size = size;
- uc->uc_nextvictim = 0;
- uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
- if (uc->uc_entries == NULL) {
- CACHE_PERROR("enablecache: could not allocate cache data");
- return(0);
- }
- BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
- uc->uc_fifo = ALLOC(cache_ptr, size);
- if (uc->uc_fifo == NULL) {
- CACHE_PERROR("enablecache: could not allocate cache fifo");
- return(0);
- }
- BZERO(uc->uc_fifo, cache_ptr, size);
- su->su_cache = (char *) uc;
- return(1);
-}
-
-
-/*
- * Set an entry in the cache
- */
-static void
-cache_set(xprt, replylen)
- SVCXPRT *xprt;
- u_long replylen;
-{
- register cache_ptr victim;
- register cache_ptr *vicp;
- register struct svcudp_data *su = su_data(xprt);
- struct udp_cache *uc = (struct udp_cache *) su->su_cache;
- u_int loc;
- char *newbuf;
-
- /*
- * Find space for the new entry, either by
- * reusing an old entry, or by mallocing a new one
- */
- victim = uc->uc_fifo[uc->uc_nextvictim];
- if (victim != NULL) {
- loc = CACHE_LOC(xprt, victim->cache_xid);
- for (vicp = &uc->uc_entries[loc];
- *vicp != NULL && *vicp != victim;
- vicp = &(*vicp)->cache_next)
- ;
- if (*vicp == NULL) {
- CACHE_PERROR("cache_set: victim not found");
- return;
- }
- *vicp = victim->cache_next; /* remote from cache */
- newbuf = victim->cache_reply;
- } else {
- victim = ALLOC(struct cache_node, 1);
- if (victim == NULL) {
- CACHE_PERROR("cache_set: victim alloc failed");
- return;
- }
- newbuf = mem_alloc(su->su_iosz);
- if (newbuf == NULL) {
- CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
- return;
- }
- }
-
- /*
- * Store it away
- */
- victim->cache_replylen = replylen;
- victim->cache_reply = rpc_buffer(xprt);
- rpc_buffer(xprt) = newbuf;
- xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
- victim->cache_xid = su->su_xid;
- victim->cache_proc = uc->uc_proc;
- victim->cache_vers = uc->uc_vers;
- victim->cache_prog = uc->uc_prog;
- victim->cache_addr = uc->uc_addr;
- loc = CACHE_LOC(xprt, victim->cache_xid);
- victim->cache_next = uc->uc_entries[loc];
- uc->uc_entries[loc] = victim;
- uc->uc_fifo[uc->uc_nextvictim++] = victim;
- uc->uc_nextvictim %= uc->uc_size;
-}
-
-/*
- * Try to get an entry from the cache
- * return 1 if found, 0 if not found
- */
-static int
-cache_get(xprt, msg, replyp, replylenp)
- SVCXPRT *xprt;
- struct rpc_msg *msg;
- char **replyp;
- u_long *replylenp;
-{
- u_int loc;
- register cache_ptr ent;
- register struct svcudp_data *su = su_data(xprt);
- register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
-
-# define EQADDR(a1, a2) (memcmp(&a1, &a2, sizeof(a1)) == 0)
-
- loc = CACHE_LOC(xprt, su->su_xid);
- for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
- if (ent->cache_xid == su->su_xid &&
- ent->cache_proc == uc->uc_proc &&
- ent->cache_vers == uc->uc_vers &&
- ent->cache_prog == uc->uc_prog &&
- EQADDR(ent->cache_addr, uc->uc_addr)) {
- *replyp = ent->cache_reply;
- *replylenp = ent->cache_replylen;
- return(1);
- }
- }
- /*
- * Failed to find entry
- * Remember a few things so we can do a set later
- */
- uc->uc_proc = msg->rm_call.cb_proc;
- uc->uc_vers = msg->rm_call.cb_vers;
- uc->uc_prog = msg->rm_call.cb_prog;
- uc->uc_addr = xprt->xp_raddr;
- return(0);
-}
-
diff --git a/lib/libc/rpc/svc_unix.c b/lib/libc/rpc/svc_unix.c
deleted file mode 100644
index 5e77c19287cc..000000000000
--- a/lib/libc/rpc/svc_unix.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD$";
-#endif
-
-/*
- * svc_unix.c, Server side for TCP/IP based RPC.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- *
- * Actually implements two flavors of transporter -
- * a unix rendezvouser (a listner and connection establisher)
- * and a record/unix stream.
- */
-
-#include "namespace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <rpc/rpc.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include "un-namespace.h"
-
-/*
- * Ops vector for AF_UNIX based rpc service handle
- */
-static bool_t svcunix_recv();
-static enum xprt_stat svcunix_stat();
-static bool_t svcunix_getargs();
-static bool_t svcunix_reply();
-static bool_t svcunix_freeargs();
-static void svcunix_destroy();
-
-static struct xp_ops svcunix_op = {
- svcunix_recv,
- svcunix_stat,
- svcunix_getargs,
- svcunix_reply,
- svcunix_freeargs,
- svcunix_destroy
-};
-
-/*
- * Ops vector for TCP/IP rendezvous handler
- */
-static bool_t rendezvous_request();
-static enum xprt_stat rendezvous_stat();
-
-static struct xp_ops svcunix_rendezvous_op = {
- rendezvous_request,
- rendezvous_stat,
- (bool_t (*)())abort,
- (bool_t (*)())abort,
- (bool_t (*)())abort,
- svcunix_destroy
-};
-
-static int readunix(), writeunix();
-static SVCXPRT *makefd_xprt();
-
-struct unix_rendezvous { /* kept in xprt->xp_p1 */
- u_int sendsize;
- u_int recvsize;
-};
-
-struct unix_conn { /* kept in xprt->xp_p1 */
- enum xprt_stat strm_stat;
- u_long x_id;
- XDR xdrs;
- char verf_body[MAX_AUTH_BYTES];
-};
-
-
-struct cmessage {
- struct cmsghdr cmsg;
- struct cmsgcred cmcred;
-};
-
-static struct cmessage cm;
-
-static int __msgread(sock, buf, cnt)
- int sock;
- void *buf;
- size_t cnt;
-{
- struct iovec iov[1];
- struct msghdr msg;
-
- bzero((char *)&cm, sizeof(cm));
- iov[0].iov_base = buf;
- iov[0].iov_len = cnt;
-
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = (caddr_t)&cm;
- msg.msg_controllen = sizeof(struct cmessage);
- msg.msg_flags = 0;
-
- return(_recvmsg(sock, &msg, 0));
-}
-
-static int __msgwrite(sock, buf, cnt)
- int sock;
- void *buf;
- size_t cnt;
-{
- struct iovec iov[1];
- struct msghdr msg;
-
- bzero((char *)&cm, sizeof(cm));
- iov[0].iov_base = buf;
- iov[0].iov_len = cnt;
-
- cm.cmsg.cmsg_type = SCM_CREDS;
- cm.cmsg.cmsg_level = SOL_SOCKET;
- cm.cmsg.cmsg_len = sizeof(struct cmessage);
-
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = (caddr_t)&cm;
- msg.msg_controllen = sizeof(struct cmessage);
- msg.msg_flags = 0;
-
- return(_sendmsg(sock, &msg, 0));
-}
-
-/*
- * Usage:
- * xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
- *
- * Creates, registers, and returns a (rpc) unix based transporter.
- * Once *xprt is initialized, it is registered as a transporter
- * see (svc.h, xprt_register). This routine returns
- * a NULL if a problem occurred.
- *
- * If sock<0 then a socket is created, else sock is used.
- * If the socket, sock is not bound to a port then svcunix_create
- * binds it to an arbitrary port. The routine then starts a unix
- * listener on the socket's associated port. In any (successful) case,
- * xprt->xp_sock is the registered socket number and xprt->xp_port is the
- * associated port number.
- *
- * Since unix streams do buffered io similar to stdio, the caller can specify
- * how big the send and receive buffers are via the second and third parms;
- * 0 => use the system default.
- */
-SVCXPRT *
-svcunix_create(sock, sendsize, recvsize, path)
- register int sock;
- u_int sendsize;
- u_int recvsize;
- char *path;
-{
- bool_t madesock = FALSE;
- register SVCXPRT *xprt;
- register struct unix_rendezvous *r;
- struct sockaddr_un addr;
- int len = sizeof(struct sockaddr_un);
-
- if (sock == RPC_ANYSOCK) {
- if ((sock = _socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror("svc_unix.c - AF_UNIX socket creation problem");
- return ((SVCXPRT *)NULL);
- }
- madesock = TRUE;
- }
- memset(&addr, 0, sizeof (addr));
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, path);
- len = strlen(addr.sun_path) + sizeof(addr.sun_family) +
- sizeof(addr.sun_len) + 1;
- addr.sun_len = len;
-
- _bind(sock, (struct sockaddr *)&addr, len);
-
- if ((_getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
- (_listen(sock, 2) != 0)) {
- perror("svc_unix.c - cannot getsockname or listen");
- if (madesock)
- (void)_close(sock);
- return ((SVCXPRT *)NULL);
- }
- r = (struct unix_rendezvous *)mem_alloc(sizeof(*r));
- if (r == NULL) {
- (void) fprintf(stderr, "svcunix_create: out of memory\n");
- return (NULL);
- }
- r->sendsize = sendsize;
- r->recvsize = recvsize;
- xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
- if (xprt == NULL) {
- (void) fprintf(stderr, "svcunix_create: out of memory\n");
- return (NULL);
- }
- xprt->xp_p2 = NULL;
- xprt->xp_p1 = (caddr_t)r;
- xprt->xp_verf = _null_auth;
- xprt->xp_ops = &svcunix_rendezvous_op;
- xprt->xp_port = -1 /*ntohs(addr.sin_port)*/;
- xprt->xp_sock = sock;
- xprt_register(xprt);
- return (xprt);
-}
-
-/*
- * Like svunix_create(), except the routine takes any *open* UNIX file
- * descriptor as its first input.
- */
-SVCXPRT *
-svcunixfd_create(fd, sendsize, recvsize)
- int fd;
- u_int sendsize;
- u_int recvsize;
-{
-
- return (makefd_xprt(fd, sendsize, recvsize));
-}
-
-static SVCXPRT *
-makefd_xprt(fd, sendsize, recvsize)
- int fd;
- u_int sendsize;
- u_int recvsize;
-{
- register SVCXPRT *xprt;
- register struct unix_conn *cd;
-
- xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
- if (xprt == (SVCXPRT *)NULL) {
- (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
- goto done;
- }
- cd = (struct unix_conn *)mem_alloc(sizeof(struct unix_conn));
- if (cd == (struct unix_conn *)NULL) {
- (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
- mem_free((char *) xprt, sizeof(SVCXPRT));
- xprt = (SVCXPRT *)NULL;
- goto done;
- }
- cd->strm_stat = XPRT_IDLE;
- xdrrec_create(&(cd->xdrs), sendsize, recvsize,
- (caddr_t)xprt, readunix, writeunix);
- xprt->xp_p2 = NULL;
- xprt->xp_p1 = (caddr_t)cd;
- xprt->xp_verf.oa_base = cd->verf_body;
- xprt->xp_addrlen = 0;
- xprt->xp_ops = &svcunix_op; /* truely deals with calls */
- xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
- xprt->xp_sock = fd;
- xprt_register(xprt);
- done:
- return (xprt);
-}
-
-static bool_t
-rendezvous_request(xprt)
- register SVCXPRT *xprt;
-{
- int sock;
- struct unix_rendezvous *r;
- struct sockaddr_un addr;
- struct sockaddr_in in_addr;
- int len;
-
- r = (struct unix_rendezvous *)xprt->xp_p1;
- again:
- len = sizeof(struct sockaddr_in);
- if ((sock = _accept(xprt->xp_sock, (struct sockaddr *)&addr,
- &len)) < 0) {
- if (errno == EINTR)
- goto again;
- return (FALSE);
- }
-
- /*
- * make a new transporter (re-uses xprt)
- */
- bzero((char *)&in_addr, sizeof(in_addr));
- in_addr.sin_family = AF_UNIX;
- xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
- xprt->xp_raddr = in_addr;
- xprt->xp_addrlen = len;
- return (FALSE); /* there is never an rpc msg to be processed */
-}
-
-static enum xprt_stat
-rendezvous_stat()
-{
-
- return (XPRT_IDLE);
-}
-
-static void
-svcunix_destroy(xprt)
- register SVCXPRT *xprt;
-{
- register struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1;
-
- xprt_unregister(xprt);
- (void)_close(xprt->xp_sock);
- if (xprt->xp_port != 0) {
- /* a rendezvouser socket */
- xprt->xp_port = 0;
- } else {
- /* an actual connection socket */
- XDR_DESTROY(&(cd->xdrs));
- }
- mem_free((caddr_t)cd, sizeof(struct unix_conn));
- mem_free((caddr_t)xprt, sizeof(SVCXPRT));
-}
-
-/*
- * All read operations timeout after 35 seconds.
- * A timeout is fatal for the connection.
- */
-static struct timeval wait_per_try = { 35, 0 };
-
-/*
- * reads data from the unix conection.
- * any error is fatal and the connection is closed.
- * (And a read of zero bytes is a half closed stream => error.)
- *
- * Note: we have to be careful here not to allow ourselves to become
- * blocked too long in this routine. While we're waiting for data from one
- * client, another client may be trying to connect. To avoid this situation,
- * some code from svc_run() is transplanted here: the _select() loop checks
- * all RPC descriptors including the one we want and calls svc_getreqset2()
- * to handle new requests if any are detected.
- */
-static int
-readunix(xprt, buf, len)
- register SVCXPRT *xprt;
- caddr_t buf;
- register int len;
-{
- register int sock = xprt->xp_sock;
- struct timeval start, delta, tv;
- struct timeval tmp1, tmp2;
- fd_set *fds;
- extern fd_set *__svc_fdset;
- extern int __svc_fdsetsize;
-
- delta = wait_per_try;
- fds = NULL;
- gettimeofday(&start, NULL);
- do {
- int bytes = howmany(__svc_fdsetsize, NFDBITS) *
- sizeof(fd_mask);
- if (fds != NULL)
- free(fds);
- fds = (fd_set *)malloc(bytes);
- if (fds == NULL)
- goto fatal_err;
- memcpy(fds, __svc_fdset, bytes);
-
- /* XXX we know the other bits are still clear */
- FD_SET(sock, fds);
- tv = delta; /* in case _select() implements writeback */
- switch (_select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
- case -1:
- FD_ZERO(fds);
- if (errno != EINTR)
- goto fatal_err;
- gettimeofday(&tmp1, NULL);
- timersub(&tmp1, &start, &tmp2);
- timersub(&wait_per_try, &tmp2, &tmp1);
- if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
- goto fatal_err;
- delta = tmp1;
- continue;
- case 0:
- goto fatal_err;
- default:
- if (!FD_ISSET(sock, fds)) {
- svc_getreqset2(fds, svc_maxfd + 1);
- gettimeofday(&tmp1, NULL);
- timersub(&tmp1, &start, &tmp2);
- timersub(&wait_per_try, &tmp2, &tmp1);
- if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
- goto fatal_err;
- delta = tmp1;
- continue;
- }
- }
- } while (!FD_ISSET(sock, fds));
- if ((len = __msgread(sock, buf, len)) > 0) {
- if (fds != NULL)
- free(fds);
- return (len);
- }
-fatal_err:
- ((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
- if (fds != NULL)
- free(fds);
- return (-1);
-}
-
-/*
- * writes data to the unix connection.
- * Any error is fatal and the connection is closed.
- */
-static int
-writeunix(xprt, buf, len)
- register SVCXPRT *xprt;
- caddr_t buf;
- int len;
-{
- register int i, cnt;
-
- for (cnt = len; cnt > 0; cnt -= i, buf += i) {
- if ((i = __msgwrite(xprt->xp_sock, buf, cnt)) < 0) {
- ((struct unix_conn *)(xprt->xp_p1))->strm_stat =
- XPRT_DIED;
- return (-1);
- }
- }
- return (len);
-}
-
-static enum xprt_stat
-svcunix_stat(xprt)
- SVCXPRT *xprt;
-{
- register struct unix_conn *cd =
- (struct unix_conn *)(xprt->xp_p1);
-
- if (cd->strm_stat == XPRT_DIED)
- return (XPRT_DIED);
- if (! xdrrec_eof(&(cd->xdrs)))
- return (XPRT_MOREREQS);
- return (XPRT_IDLE);
-}
-
-static bool_t
-svcunix_recv(xprt, msg)
- SVCXPRT *xprt;
- register struct rpc_msg *msg;
-{
- register struct unix_conn *cd =
- (struct unix_conn *)(xprt->xp_p1);
- register XDR *xdrs = &(cd->xdrs);
-
- xdrs->x_op = XDR_DECODE;
- (void)xdrrec_skiprecord(xdrs);
- if (xdr_callmsg(xdrs, msg)) {
- cd->x_id = msg->rm_xid;
- /* set up verifiers */
- msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
- msg->rm_call.cb_verf.oa_base = (caddr_t)&cm;
- msg->rm_call.cb_verf.oa_length = sizeof(cm);
- return (TRUE);
- }
- cd->strm_stat = XPRT_DIED; /* XXXX */
- return (FALSE);
-}
-
-static bool_t
-svcunix_getargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
-
- return ((*xdr_args)(&(((struct unix_conn *)(xprt->xp_p1))->xdrs), args_ptr));
-}
-
-static bool_t
-svcunix_freeargs(xprt, xdr_args, args_ptr)
- SVCXPRT *xprt;
- xdrproc_t xdr_args;
- caddr_t args_ptr;
-{
- register XDR *xdrs =
- &(((struct unix_conn *)(xprt->xp_p1))->xdrs);
-
- xdrs->x_op = XDR_FREE;
- return ((*xdr_args)(xdrs, args_ptr));
-}
-
-static bool_t
-svcunix_reply(xprt, msg)
- SVCXPRT *xprt;
- register struct rpc_msg *msg;
-{
- register struct unix_conn *cd =
- (struct unix_conn *)(xprt->xp_p1);
- register XDR *xdrs = &(cd->xdrs);
- register bool_t stat;
-
- xdrs->x_op = XDR_ENCODE;
- msg->rm_xid = cd->x_id;
- stat = xdr_replymsg(xdrs, msg);
- (void)xdrrec_endofrecord(xdrs, TRUE);
- return (stat);
-}
diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c
new file mode 100644
index 000000000000..add21ee8097e
--- /dev/null
+++ b/lib/libc/rpc/svc_vc.c
@@ -0,0 +1,689 @@
+/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+
+/*
+ * svc_vc.c, Server side for Connection Oriented based RPC.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include "reentrant.h"
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+
+#include "rpc_com.h"
+#include "un-namespace.h"
+
+#define SOCKCREDSIZE(ngrps) \
+ (sizeof(struct cmsgcred) + (sizeof(gid_t) * ((ngrps) - 1)))
+
+static SVCXPRT *makefd_xprt __P((int, u_int, u_int));
+static bool_t rendezvous_request __P((SVCXPRT *, struct rpc_msg *));
+static enum xprt_stat rendezvous_stat __P((SVCXPRT *));
+static void svc_vc_destroy __P((SVCXPRT *));
+static int read_vc __P((caddr_t, caddr_t, int));
+static int write_vc __P((caddr_t, caddr_t, int));
+static enum xprt_stat svc_vc_stat __P((SVCXPRT *));
+static bool_t svc_vc_recv __P((SVCXPRT *, struct rpc_msg *));
+static bool_t svc_vc_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static bool_t svc_vc_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
+static bool_t svc_vc_reply __P((SVCXPRT *, struct rpc_msg *));
+static void svc_vc_rendezvous_ops __P((SVCXPRT *));
+static void svc_vc_ops __P((SVCXPRT *));
+static bool_t svc_vc_control __P((SVCXPRT *xprt, const u_int rq, void *in));
+static int __msgwrite(int, void *, size_t);
+static int __msgread(int, void *, size_t);
+
+struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
+ u_int sendsize;
+ u_int recvsize;
+};
+
+struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
+ enum xprt_stat strm_stat;
+ u_int32_t x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+
+/*
+ * Usage:
+ * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register). This routine returns
+ * a NULL if a problem occurred.
+ *
+ * The filedescriptor passed in is expected to refer to a bound, but
+ * not yet connected socket.
+ *
+ * Since streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svc_vc_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct cf_rendezvous *r = NULL;
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage sslocal;
+ socklen_t slen;
+ int one = 1;
+
+ r = mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ warnx("svc_vc_create: out of memory");
+ goto cleanup_svc_vc_create;
+ }
+ if (!__rpc_fd2sockinfo(fd, &si))
+ return NULL;
+ r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+ r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+ xprt = mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ warnx("svc_vc_create: out of memory");
+ goto cleanup_svc_vc_create;
+ }
+ xprt->xp_tp = NULL;
+ xprt->xp_p1 = (caddr_t)(void *)r;
+ xprt->xp_p2 = NULL;
+ xprt->xp_p3 = NULL;
+ xprt->xp_verf = _null_auth;
+ svc_vc_rendezvous_ops(xprt);
+ xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
+ xprt->xp_fd = fd;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
+ warnx("svc_vc_create: could not retrieve local addr");
+ goto cleanup_svc_vc_create;
+ }
+
+ xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
+ xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
+ if (xprt->xp_ltaddr.buf == NULL) {
+ warnx("svc_vc_create: no mem for local addr");
+ goto cleanup_svc_vc_create;
+ }
+ memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
+
+ xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+ xprt_register(xprt);
+ return (xprt);
+cleanup_svc_vc_create:
+ if (r != NULL)
+ mem_free(r, sizeof(*r));
+ return (NULL);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svc_fd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ SVCXPRT *ret;
+
+ assert(fd != -1);
+
+ ret = makefd_xprt(fd, sendsize, recvsize);
+ if (ret == NULL)
+ return NULL;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx("svc_fd_create: could not retrieve local addr");
+ goto freedata;
+ }
+ ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
+ ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
+ if (ret->xp_ltaddr.buf == NULL) {
+ warnx("svc_fd_create: no mem for local addr");
+ goto freedata;
+ }
+ memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx("svc_fd_create: could not retrieve remote addr");
+ goto freedata;
+ }
+ ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
+ ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
+ if (ret->xp_rtaddr.buf == NULL) {
+ warnx("svc_fd_create: no mem for local addr");
+ goto freedata;
+ }
+ memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
+#ifdef PORTMAP
+ if (ss.ss_family == AF_INET) {
+ ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
+ ret->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+
+ return ret;
+
+freedata:
+ if (ret->xp_ltaddr.buf != NULL)
+ mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
+
+ return NULL;
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct cf_conn *cd;
+ const char *netid;
+ struct __rpc_sockinfo si;
+
+ assert(fd != -1);
+
+ xprt = mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ warnx("svc_vc: makefd_xprt: out of memory");
+ goto done;
+ }
+ memset(xprt, 0, sizeof *xprt);
+ cd = mem_alloc(sizeof(struct cf_conn));
+ if (cd == NULL) {
+ warnx("svc_tcp: makefd_xprt: out of memory");
+ mem_free(xprt, sizeof(SVCXPRT));
+ xprt = NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)(void *)xprt, read_vc, write_vc);
+ xprt->xp_p1 = (caddr_t)(void *)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ svc_vc_ops(xprt); /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_fd = fd;
+ if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
+ xprt->xp_netid = strdup(netid);
+
+ xprt_register(xprt);
+done:
+ return (xprt);
+}
+
+/*ARGSUSED*/
+static bool_t
+rendezvous_request(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ int sock;
+ struct cf_rendezvous *r;
+ struct sockaddr_storage addr;
+ socklen_t len;
+ struct __rpc_sockinfo si;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ r = (struct cf_rendezvous *)xprt->xp_p1;
+again:
+ len = sizeof addr;
+ if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_rtaddr.buf = mem_alloc(len);
+ if (xprt->xp_rtaddr.buf == NULL)
+ return (FALSE);
+ memcpy(xprt->xp_rtaddr.buf, &addr, len);
+ xprt->xp_rtaddr.len = len;
+#ifdef PORTMAP
+ if (addr.ss_family == AF_INET) {
+ xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf;
+ xprt->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+ if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
+ len = 1;
+ /* XXX fvdl - is this useful? */
+ _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
+ }
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+rendezvous_stat(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svc_vc_destroy(xprt)
+ SVCXPRT *xprt;
+{
+ struct cf_conn *cd;
+ struct cf_rendezvous *r;
+
+ assert(xprt != NULL);
+
+ cd = (struct cf_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ if (xprt->xp_fd != RPC_ANYFD)
+ (void)_close(xprt->xp_fd);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ r = (struct cf_rendezvous *)xprt->xp_p1;
+ mem_free(r, sizeof (struct cf_rendezvous));
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ mem_free(cd, sizeof(struct cf_conn));
+ }
+ if (xprt->xp_rtaddr.buf)
+ mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+ if (xprt->xp_ltaddr.buf)
+ mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+ if (xprt->xp_tp)
+ free(xprt->xp_tp);
+ if (xprt->xp_netid)
+ free(xprt->xp_netid);
+ mem_free(xprt, sizeof(SVCXPRT));
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_vc_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
+}
+
+/*
+ * reads data from the tcp or uip connection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ * All read operations timeout after 35 seconds. A timeout is
+ * fatal for the connection.
+ */
+static int
+read_vc(xprtp, buf, len)
+ caddr_t xprtp;
+ caddr_t buf;
+ int len;
+{
+ SVCXPRT *xprt;
+ int sock;
+ int milliseconds = 35 * 1000;
+ struct pollfd pollfd;
+ struct sockaddr *sa;
+ struct cmessage *cm;
+ struct cmsghdr *cmp;
+ struct sockcred *sc;
+
+ xprt = (SVCXPRT *)(void *)xprtp;
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
+
+ do {
+ pollfd.fd = sock;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ switch (_poll(&pollfd, 1, milliseconds)) {
+ case -1:
+ if (errno == EINTR) {
+ continue;
+ }
+ /*FALLTHROUGH*/
+ case 0:
+ goto fatal_err;
+
+ default:
+ break;
+ }
+ } while ((pollfd.revents & POLLIN) == 0);
+
+ sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
+ if (sa->sa_family == AF_LOCAL) {
+ if ((len = __msgread(sock, buf, len)) > 0) {
+ cm = (struct cmessage *)xprt->xp_verf.oa_base;
+ cmp = &cm->cmsg;
+ sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
+ xprt->xp_p2 = sc;
+ return (len);
+ }
+ } else {
+ if ((len = _read(sock, buf, (size_t)len)) > 0)
+ return (len);
+ }
+
+fatal_err:
+ ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+write_vc(xprtp, buf, len)
+ caddr_t xprtp;
+ caddr_t buf;
+ int len;
+{
+ SVCXPRT *xprt;
+ int i, cnt;
+ struct sockaddr *sa;
+
+ xprt = (SVCXPRT *)(void *)xprtp;
+ assert(xprt != NULL);
+
+ sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
+ if (sa->sa_family == AF_LOCAL) {
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(xprt->xp_fd, buf,
+ (size_t)cnt)) < 0) {
+ ((struct cf_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ } else {
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = _write(xprt->xp_fd, buf,
+ (size_t)cnt)) < 0) {
+ ((struct cf_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ }
+
+ return (len);
+}
+
+static enum xprt_stat
+svc_vc_stat(xprt)
+ SVCXPRT *xprt;
+{
+ struct cf_conn *cd;
+
+ assert(xprt != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+
+ if (cd->strm_stat == XPRT_DIED)
+ return (XPRT_DIED);
+ if (! xdrrec_eof(&(cd->xdrs)))
+ return (XPRT_MOREREQS);
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svc_vc_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct cf_conn *cd;
+ XDR *xdrs;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+ xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ return (TRUE);
+ }
+ cd->strm_stat = XPRT_DIED;
+ return (FALSE);
+}
+
+static bool_t
+svc_vc_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ assert(xprt != NULL);
+ /* args_ptr may be NULL */
+ return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs),
+ args_ptr));
+}
+
+static bool_t
+svc_vc_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ XDR *xdrs;
+
+ assert(xprt != NULL);
+ /* args_ptr may be NULL */
+
+ xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svc_vc_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct cf_conn *cd;
+ XDR *xdrs;
+ bool_t stat;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+ xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = xdr_replymsg(xdrs, msg);
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
+
+static void
+svc_vc_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+ extern mutex_t ops_lock;
+
+/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_vc_recv;
+ ops.xp_stat = svc_vc_stat;
+ ops.xp_getargs = svc_vc_getargs;
+ ops.xp_reply = svc_vc_reply;
+ ops.xp_freeargs = svc_vc_freeargs;
+ ops.xp_destroy = svc_vc_destroy;
+ ops2.xp_control = svc_vc_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+static void
+svc_vc_rendezvous_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+ extern mutex_t ops_lock;
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = rendezvous_request;
+ ops.xp_stat = rendezvous_stat;
+ ops.xp_getargs =
+ (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort;
+ ops.xp_reply =
+ (bool_t (*) __P((SVCXPRT *, struct rpc_msg *)))abort;
+ ops.xp_freeargs =
+ (bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort,
+ ops.xp_destroy = svc_vc_destroy;
+ ops2.xp_control = svc_vc_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+static int
+__msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(_recvmsg(sock, &msg, 0));
+}
+
+static int
+__msgwrite(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ cm.cmsg.cmsg_type = SCM_CREDS;
+ cm.cmsg.cmsg_level = SOL_SOCKET;
+ cm.cmsg.cmsg_len = sizeof(struct cmessage);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(_sendmsg(sock, &msg, 0));
+}
diff --git a/lib/libc/xdr/Makefile.inc b/lib/libc/xdr/Makefile.inc
index 1837ef889a38..62ab805b4c18 100644
--- a/lib/libc/xdr/Makefile.inc
+++ b/lib/libc/xdr/Makefile.inc
@@ -3,12 +3,19 @@
.PATH: ${.CURDIR}/../libc/xdr ${.CURDIR}/.
SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c \
- xdr_rec.c xdr_reference.c xdr_stdio.c xdr_sizeof.c
+ xdr_rec.c xdr_reference.c xdr_stdio.c
.if ${LIB} == "c"
MAN3+= xdr.3
-MLINKS+= xdr.3 xdr_array.3 \
+MLINKS+= rpc_xdr.3 xdr_accepted_reply.3 \
+ rpc_xdr.3 xdr_authsys_parms.3 \
+ rpc_xdr.3 xdr_callhdr.3 \
+ rpc_xdr.3 xdr_callmsg.3 \
+ rpc_xdr.3 xdr_opaque_auth.3 \
+ rpc_xdr.3 xdr_rejected_reply.3 \
+ rpc_xdr.3 xdr_replymsg.3 \
+ xdr.3 xdr_array.3 \
xdr.3 xdr_bool.3 \
xdr.3 xdr_bytes.3 \
xdr.3 xdr_char.3 \
@@ -32,6 +39,8 @@ MLINKS+= xdr.3 xdr_array.3 \
xdr.3 xdr_setpos.3 \
xdr.3 xdr_short.3 \
xdr.3 xdrstdio_create.3 \
+ xdr.3 xdr_short.3 \
+ xdr.3 xdrstdio_create.3 \
xdr.3 xdr_string.3 \
xdr.3 xdr_u_char.3 \
xdr.3 xdr_u_long.3 \
@@ -39,5 +48,5 @@ MLINKS+= xdr.3 xdr_array.3 \
xdr.3 xdr_union.3 \
xdr.3 xdr_vector.3 \
xdr.3 xdr_void.3 \
- xdr.3 xdr_wrapstring.3
+ xdr.3 xdr_wrapstring.3
.endif
diff --git a/lib/libc/xdr/xdr.3 b/lib/libc/xdr/xdr.3
index 49266e5026c3..35554a7478ba 100644
--- a/lib/libc/xdr/xdr.3
+++ b/lib/libc/xdr/xdr.3
@@ -5,7 +5,44 @@
.Dt XDR 3
.Os
.Sh NAME
-.Nm xdr
+.Nm xdr ,
+.Nm xdr_array ,
+.Nm xdr_bool ,
+.Nm xdr_bytes ,
+.Nm xdr_char ,
+.Nm xdr_destroy ,
+.Nm xdr_double ,
+.Nm xdr_enum ,
+.Nm xdr_float ,
+.Nm xdr_free ,
+.Nm xdr_getpos ,
+.Nm xdr_hyper ,
+.Nm xdr_inline ,
+.Nm xdr_int ,
+.Nm xdr_long ,
+.Nm xdr_longlong_t ,
+.Nm xdrmem_create ,
+.Nm xdr_opaque ,
+.Nm xdr_pointer ,
+.Nm xdrrec_create ,
+.Nm xdrrec_endofrecord ,
+.Nm xdrrec_eof ,
+.Nm xdrrec_skiprecord ,
+.Nm xdr_reference ,
+.Nm xdr_setpos ,
+.Nm xdr_short ,
+.Nm xdrstdio_create ,
+.Nm xdr_string ,
+.Nm xdr_u_char ,
+.Nm xdr_u_hyper ,
+.Nm xdr_u_int ,
+.Nm xdr_u_long ,
+.Nm xdr_u_longlong_t ,
+.Nm xdr_u_short ,
+.Nm xdr_union ,
+.Nm xdr_vector ,
+.Nm xdr_void ,
+.Nm xdr_wrapstring
.Nd "library routines for external data representation"
.Sh LIBRARY
.Lb libc
@@ -212,6 +249,17 @@ although the
stream instances need not guarantee this.
.Pp
.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_hyper "XDR *xdrs" "longlong_t *llp"
+.Xc
+A filter primitive that translates between ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
.Ft "long *"
.Xc
.It Xo
@@ -262,6 +310,17 @@ integers and their external representations.
This routine returns one if it succeeds, zero otherwise.
.Pp
.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_longlong_t "XDR *xdrs" "longlong_t *llp"
+.Xc
+A filter primitive that translates between ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
.Ft void
.Xc
.It Xo
@@ -568,6 +627,19 @@ This routine returns one if it succeeds, zero otherwise.
.Ft int
.Xc
.It Xo
+.Fn xdr_u_hyper "XDR *xdrs" "u_longlong_t *ullp"
+.Xc
+A filter primitive that translates between
+.Vt unsigned
+ANSI C
+.Vt long long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
.Fn xdr_u_int "XDR *xdrs" "unsigned *up"
.Xc
.Pp
@@ -592,6 +664,19 @@ This routine returns one if it succeeds, zero otherwise.
.Ft int
.Xc
.It Xo
+.Fn xdr_u_longlong_t "XDR *xdrs" "u_longlong_t *ullp"
+.Xc
+A filter primitive that translates between
+.Vt unsigned
+ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
.Fn xdr_u_short "XDR *xdrs" "unsigned short *usp"
.Xc
.Pp
diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c
index 50b68fb14755..113ac3cd0a68 100644
--- a/lib/libc/xdr/xdr.c
+++ b/lib/libc/xdr/xdr.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
@@ -43,12 +46,18 @@ static char *rcsid = "$FreeBSD$";
* xdr.
*/
+#include "namespace.h"
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+typedef quad_t longlong_t; /* ANSI long long type */
+typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */
/*
* constants specific to the xdr "protocol"
@@ -60,7 +69,7 @@ static char *rcsid = "$FreeBSD$";
/*
* for unit alignment
*/
-static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
/*
* Free a data structure using XDR
@@ -72,7 +81,7 @@ xdr_free(proc, objp)
char *objp;
{
XDR x;
-
+
x.x_op = XDR_FREE;
(*proc)(&x, objp);
}
@@ -116,6 +125,7 @@ xdr_int(xdrs, ip)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -145,6 +155,7 @@ xdr_u_int(xdrs, up)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -155,7 +166,7 @@ xdr_u_int(xdrs, up)
*/
bool_t
xdr_long(xdrs, lp)
- register XDR *xdrs;
+ XDR *xdrs;
long *lp;
{
switch (xdrs->x_op) {
@@ -166,7 +177,7 @@ xdr_long(xdrs, lp)
case XDR_FREE:
return (TRUE);
}
-
+ /* NOTREACHED */
return (FALSE);
}
@@ -176,7 +187,7 @@ xdr_long(xdrs, lp)
*/
bool_t
xdr_u_long(xdrs, ulp)
- register XDR *xdrs;
+ XDR *xdrs;
u_long *ulp;
{
switch (xdrs->x_op) {
@@ -187,6 +198,7 @@ xdr_u_long(xdrs, ulp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -197,7 +209,7 @@ xdr_u_long(xdrs, ulp)
*/
bool_t
xdr_int32_t(xdrs, int32_p)
- register XDR *xdrs;
+ XDR *xdrs;
int32_t *int32_p;
{
long l;
@@ -218,6 +230,7 @@ xdr_int32_t(xdrs, int32_p)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -227,7 +240,7 @@ xdr_int32_t(xdrs, int32_p)
*/
bool_t
xdr_u_int32_t(xdrs, u_int32_p)
- register XDR *xdrs;
+ XDR *xdrs;
u_int32_t *u_int32_p;
{
u_long l;
@@ -248,71 +261,7 @@ xdr_u_int32_t(xdrs, u_int32_p)
case XDR_FREE:
return (TRUE);
}
- return (FALSE);
-}
-
-/*
- * XDR 64-bit integers
- */
-bool_t
-xdr_int64_t(xdrs, int64_p)
- register XDR *xdrs;
- int64_t *int64_p;
-{
- u_long ul[2];
-
- switch (xdrs->x_op) {
-
- case XDR_ENCODE:
- ul[0] = (u_long)((u_int64_t)*int64_p >> 32) & 0xffffffff;
- ul[1] = (u_long)((u_int64_t)*int64_p) & 0xffffffff;
- if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
- return (FALSE);
- return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
- case XDR_DECODE:
- if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
- return (FALSE);
- if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
- return (FALSE);
- *int64_p = (int64_t)
- (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
- return (TRUE);
- case XDR_FREE:
- return (TRUE);
- }
- return (FALSE);
-}
-
-/*
- * XDR unsigned 64-bit integers
- */
-bool_t
-xdr_u_int64_t(xdrs, uint64_p)
- register XDR *xdrs;
- u_int64_t *uint64_p;
-{
- u_long ul[2];
-
- switch (xdrs->x_op) {
-
- case XDR_ENCODE:
- ul[0] = (u_long)(*uint64_p >> 32) & 0xffffffff;
- ul[1] = (u_long)(*uint64_p) & 0xffffffff;
- if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
- return (FALSE);
- return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
-
- case XDR_DECODE:
- if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
- return (FALSE);
- if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
- return (FALSE);
- *uint64_p = (u_int64_t)
- (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
- return (TRUE);
- case XDR_FREE:
- return (TRUE);
- }
+ /* NOTREACHED */
return (FALSE);
}
@@ -322,7 +271,7 @@ xdr_u_int64_t(xdrs, uint64_p)
*/
bool_t
xdr_short(xdrs, sp)
- register XDR *xdrs;
+ XDR *xdrs;
short *sp;
{
long l;
@@ -343,6 +292,7 @@ xdr_short(xdrs, sp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -351,7 +301,7 @@ xdr_short(xdrs, sp)
*/
bool_t
xdr_u_short(xdrs, usp)
- register XDR *xdrs;
+ XDR *xdrs;
u_short *usp;
{
u_long l;
@@ -372,6 +322,7 @@ xdr_u_short(xdrs, usp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -381,7 +332,7 @@ xdr_u_short(xdrs, usp)
*/
bool_t
xdr_int16_t(xdrs, int16_p)
- register XDR *xdrs;
+ XDR *xdrs;
int16_t *int16_p;
{
long l;
@@ -402,6 +353,7 @@ xdr_int16_t(xdrs, int16_p)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -410,7 +362,7 @@ xdr_int16_t(xdrs, int16_p)
*/
bool_t
xdr_u_int16_t(xdrs, u_int16_p)
- register XDR *xdrs;
+ XDR *xdrs;
u_int16_t *u_int16_p;
{
u_long l;
@@ -431,6 +383,7 @@ xdr_u_int16_t(xdrs, u_int16_p)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -476,7 +429,7 @@ xdr_u_char(xdrs, cp)
*/
bool_t
xdr_bool(xdrs, bp)
- register XDR *xdrs;
+ XDR *xdrs;
bool_t *bp;
{
long lb;
@@ -497,6 +450,7 @@ xdr_bool(xdrs, bp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -508,26 +462,20 @@ xdr_enum(xdrs, ep)
XDR *xdrs;
enum_t *ep;
{
-#ifndef lint
enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
/*
* enums are treated as ints
*/
- if (sizeof (enum sizecheck) == sizeof (long)) {
- return (xdr_long(xdrs, (long *)ep));
- } else if (sizeof (enum sizecheck) == sizeof (int)) {
- return (xdr_int(xdrs, (int *)ep));
- } else if (sizeof (enum sizecheck) == sizeof (short)) {
- return (xdr_short(xdrs, (short *)ep));
+ /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)(void *)ep));
+ } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
+ return (xdr_int(xdrs, (int *)(void *)ep));
+ } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)(void *)ep));
} else {
return (FALSE);
}
-#else
- (void) (xdr_short(xdrs, (short *)ep));
- (void) (xdr_int(xdrs, (int *)ep));
- return (xdr_long(xdrs, (long *)ep));
-#endif
}
/*
@@ -537,12 +485,12 @@ xdr_enum(xdrs, ep)
*/
bool_t
xdr_opaque(xdrs, cp, cnt)
- register XDR *xdrs;
+ XDR *xdrs;
caddr_t cp;
- register u_int cnt;
+ u_int cnt;
{
- register u_int rndup;
- static crud[BYTES_PER_XDR_UNIT];
+ u_int rndup;
+ static int crud[BYTES_PER_XDR_UNIT];
/*
* if no data we are done
@@ -563,7 +511,7 @@ xdr_opaque(xdrs, cp, cnt)
}
if (rndup == 0)
return (TRUE);
- return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
+ return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
}
if (xdrs->x_op == XDR_ENCODE) {
@@ -589,13 +537,13 @@ xdr_opaque(xdrs, cp, cnt)
*/
bool_t
xdr_bytes(xdrs, cpp, sizep, maxsize)
- register XDR *xdrs;
+ XDR *xdrs;
char **cpp;
- register u_int *sizep;
+ u_int *sizep;
u_int maxsize;
{
- register char *sp = *cpp; /* sp is the actual string pointer */
- register u_int nodesize;
+ char *sp = *cpp; /* sp is the actual string pointer */
+ u_int nodesize;
/*
* first deal with the length since xdr bytes are counted
@@ -618,13 +566,13 @@ xdr_bytes(xdrs, cpp, sizep, maxsize)
return (TRUE);
}
if (sp == NULL) {
- *cpp = sp = (char *)mem_alloc(nodesize);
+ *cpp = sp = mem_alloc(nodesize);
}
if (sp == NULL) {
- (void) fprintf(stderr, "xdr_bytes: out of memory\n");
+ warnx("xdr_bytes: out of memory");
return (FALSE);
}
- /* fall into ... */
+ /* FALLTHROUGH */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, nodesize));
@@ -636,6 +584,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize)
}
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
@@ -664,13 +613,13 @@ xdr_netobj(xdrs, np)
*/
bool_t
xdr_union(xdrs, dscmp, unp, choices, dfault)
- register XDR *xdrs;
+ XDR *xdrs;
enum_t *dscmp; /* enum to decide which arm to work on */
char *unp; /* the union itself */
- struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
xdrproc_t dfault; /* default xdr routine */
{
- register enum_t dscm;
+ enum_t dscm;
/*
* we deal with the discriminator; it's an enum
@@ -686,14 +635,14 @@ xdr_union(xdrs, dscmp, unp, choices, dfault)
*/
for (; choices->proc != NULL_xdrproc_t; choices++) {
if (choices->value == dscm)
- return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+ return ((*(choices->proc))(xdrs, unp));
}
/*
* no match - execute the default xdr routine if there is one
*/
return ((dfault == NULL_xdrproc_t) ? FALSE :
- (*dfault)(xdrs, unp, LASTUNSIGNED));
+ (*dfault)(xdrs, unp));
}
@@ -713,11 +662,11 @@ xdr_union(xdrs, dscmp, unp, choices, dfault)
*/
bool_t
xdr_string(xdrs, cpp, maxsize)
- register XDR *xdrs;
+ XDR *xdrs;
char **cpp;
u_int maxsize;
{
- register char *sp = *cpp; /* sp is the actual string pointer */
+ char *sp = *cpp; /* sp is the actual string pointer */
u_int size;
u_int nodesize;
@@ -729,10 +678,12 @@ xdr_string(xdrs, cpp, maxsize)
if (sp == NULL) {
return(TRUE); /* already free */
}
- /* fall through... */
+ /* FALLTHROUGH */
case XDR_ENCODE:
size = strlen(sp);
break;
+ case XDR_DECODE:
+ break;
}
if (! xdr_u_int(xdrs, &size)) {
return (FALSE);
@@ -752,13 +703,13 @@ xdr_string(xdrs, cpp, maxsize)
return (TRUE);
}
if (sp == NULL)
- *cpp = sp = (char *)mem_alloc(nodesize);
+ *cpp = sp = mem_alloc(nodesize);
if (sp == NULL) {
- (void) fprintf(stderr, "xdr_string: out of memory\n");
+ warnx("xdr_string: out of memory");
return (FALSE);
}
sp[size] = 0;
- /* fall into ... */
+ /* FALLTHROUGH */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, size));
@@ -768,11 +719,12 @@ xdr_string(xdrs, cpp, maxsize)
*cpp = NULL;
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
-/*
- * Wrapper for xdr_string that can be called directly from
+/*
+ * Wrapper for xdr_string that can be called directly from
* routines like clnt_call
*/
bool_t
@@ -782,3 +734,144 @@ xdr_wrapstring(xdrs, cpp)
{
return xdr_string(xdrs, cpp, LASTUNSIGNED);
}
+
+/*
+ * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
+ * are in the "non-portable" section because they require that a `long long'
+ * be a 64-bit type.
+ *
+ * --thorpej@netbsd.org, November 30, 1999
+ */
+
+/*
+ * XDR 64-bit integers
+ */
+bool_t
+xdr_int64_t(xdrs, llp)
+ XDR *xdrs;
+ int64_t *llp;
+{
+ u_long ul[2];
+
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
+ ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
+ if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
+ case XDR_DECODE:
+ if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
+ return (FALSE);
+ *llp = (int64_t)
+ (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
+ return (TRUE);
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR unsigned 64-bit integers
+ */
+bool_t
+xdr_u_int64_t(xdrs, ullp)
+ XDR *xdrs;
+ u_int64_t *ullp;
+{
+ u_long ul[2];
+
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
+ ul[1] = (u_long)(*ullp) & 0xffffffff;
+ if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
+ case XDR_DECODE:
+ if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
+ return (FALSE);
+ *ullp = (u_int64_t)
+ (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
+ return (TRUE);
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR hypers
+ */
+bool_t
+xdr_hyper(xdrs, llp)
+ XDR *xdrs;
+ longlong_t *llp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_int64_t().
+ */
+ return (xdr_int64_t(xdrs, (int64_t *)llp));
+}
+
+
+/*
+ * XDR unsigned hypers
+ */
+bool_t
+xdr_u_hyper(xdrs, ullp)
+ XDR *xdrs;
+ u_longlong_t *ullp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_u_int64_t().
+ */
+ return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
+}
+
+
+/*
+ * XDR longlong_t's
+ */
+bool_t
+xdr_longlong_t(xdrs, llp)
+ XDR *xdrs;
+ longlong_t *llp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_int64_t().
+ */
+ return (xdr_int64_t(xdrs, (int64_t *)llp));
+}
+
+
+/*
+ * XDR u_longlong_t's
+ */
+bool_t
+xdr_u_longlong_t(xdrs, ullp)
+ XDR *xdrs;
+ u_longlong_t *ullp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_u_int64_t().
+ */
+ return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
+}
diff --git a/lib/libc/xdr/xdr_array.c b/lib/libc/xdr/xdr_array.c
index b7d36fea5ca3..8e0a302441a0 100644
--- a/lib/libc/xdr/xdr_array.c
+++ b/lib/libc/xdr/xdr_array.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_array.c,v 1.12 2000/01/22 22:19:18 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
@@ -42,13 +45,15 @@ static char *rcsid = "$FreeBSD$";
* arrays. See xdr.h for more info on the interface to xdr.
*/
+#include "namespace.h"
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
-
-#define LASTUNSIGNED ((u_int) 0-1)
+#include "un-namespace.h"
/*
* XDR an array of arbitrary elements
@@ -59,18 +64,18 @@ static char *rcsid = "$FreeBSD$";
*/
bool_t
xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
- register XDR *xdrs;
+ XDR *xdrs;
caddr_t *addrp; /* array pointer */
u_int *sizep; /* number of elements */
u_int maxsize; /* max numberof elements */
u_int elsize; /* size in bytes of each element */
xdrproc_t elproc; /* xdr routine to handle each element */
{
- register u_int i;
- register caddr_t target = *addrp;
- register u_int c; /* the actual element count */
- register bool_t stat = TRUE;
- register u_int nodesize;
+ u_int i;
+ caddr_t target = *addrp;
+ u_int c; /* the actual element count */
+ bool_t stat = TRUE;
+ u_int nodesize;
/* like strings, arrays are really counted arrays */
if (! xdr_u_int(xdrs, sizep)) {
@@ -93,8 +98,7 @@ xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
return (TRUE);
*addrp = target = mem_alloc(nodesize);
if (target == NULL) {
- (void) fprintf(stderr,
- "xdr_array: out of memory\n");
+ warnx("xdr_array: out of memory");
return (FALSE);
}
memset(target, 0, nodesize);
@@ -102,13 +106,16 @@ xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
case XDR_FREE:
return (TRUE);
- }
+ case XDR_ENCODE:
+ break;
+ }
+
/*
* now we xdr each element of array
*/
for (i = 0; (i < c) && stat; i++) {
- stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+ stat = (*elproc)(xdrs, target);
target += elsize;
}
@@ -134,22 +141,21 @@ xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
*/
bool_t
xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
- register XDR *xdrs;
- register char *basep;
- register u_int nelem;
- register u_int elemsize;
- register xdrproc_t xdr_elem;
+ XDR *xdrs;
+ char *basep;
+ u_int nelem;
+ u_int elemsize;
+ xdrproc_t xdr_elem;
{
- register u_int i;
- register char *elptr;
+ u_int i;
+ char *elptr;
elptr = basep;
for (i = 0; i < nelem; i++) {
- if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+ if (! (*xdr_elem)(xdrs, elptr)) {
return(FALSE);
}
elptr += elemsize;
}
- return(TRUE);
+ return(TRUE);
}
-
diff --git a/lib/libc/xdr/xdr_float.c b/lib/libc/xdr/xdr_float.c
index 3966320b7298..024888f834a1 100644
--- a/lib/libc/xdr/xdr_float.c
+++ b/lib/libc/xdr/xdr_float.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,14 +29,15 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
/*
- * xdr_float.c, Generic XDR routines impelmentation.
+ * xdr_float.c, Generic XDR routines implementation.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
@@ -43,11 +46,15 @@ static char *rcsid = "$FreeBSD$";
* xdr.
*/
-#include <stdio.h>
+#include "namespace.h"
#include <sys/types.h>
#include <sys/param.h>
+
+#include <stdio.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
+#include "un-namespace.h"
/*
* NB: Not portable.
@@ -56,12 +63,13 @@ static char *rcsid = "$FreeBSD$";
#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
- defined(__arm32__) || defined(__ppc__) || defined(__ia64__)
+ defined(__arm32__) || defined(__ppc__) || defined(__ia64__) || \
+ defined(__arm26__)
#include <machine/endian.h>
#define IEEEFP
#endif
-#ifdef vax
+#if defined(__vax__)
/* What IEEE single precision floating point looks like on a Vax */
struct ieee_single {
@@ -94,13 +102,10 @@ static struct sgl_limits {
bool_t
xdr_float(xdrs, fp)
- register XDR *xdrs;
- register float *fp;
+ XDR *xdrs;
+ float *fp;
{
-#ifdef IEEEFP
- bool_t rv;
- long tmpl;
-#else
+#ifndef IEEEFP
struct ieee_single is;
struct vax_single vs, *vsp;
struct sgl_limits *lim;
@@ -110,8 +115,7 @@ xdr_float(xdrs, fp)
case XDR_ENCODE:
#ifdef IEEEFP
- tmpl = *(int32_t *)fp;
- return (XDR_PUTLONG(xdrs, &tmpl));
+ return (XDR_PUTINT32(xdrs, (int32_t *)fp));
#else
vs = *((struct vax_single *)fp);
for (i = 0, lim = sgl_limits;
@@ -128,17 +132,15 @@ xdr_float(xdrs, fp)
is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
shipit:
is.sign = vs.sign;
- return (XDR_PUTLONG(xdrs, (long *)&is));
+ return (XDR_PUTINT32(xdrs, (int32_t *)&is));
#endif
case XDR_DECODE:
#ifdef IEEEFP
- rv = XDR_GETLONG(xdrs, &tmpl);
- *(int32_t *)fp = tmpl;
- return (rv);
+ return (XDR_GETINT32(xdrs, (int32_t *)fp));
#else
vsp = (struct vax_single *)fp;
- if (!XDR_GETLONG(xdrs, (long *)&is))
+ if (!XDR_GETINT32(xdrs, (int32_t *)&is))
return (FALSE);
for (i = 0, lim = sgl_limits;
i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
@@ -160,10 +162,11 @@ xdr_float(xdrs, fp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
-#ifdef vax
+#if defined(__vax__)
/* What IEEE double precision floating point looks like on a Vax */
struct ieee_double {
unsigned int mantissa1 : 20;
@@ -201,18 +204,17 @@ static struct dbl_limits {
bool_t
xdr_double(xdrs, dp)
- register XDR *xdrs;
+ XDR *xdrs;
double *dp;
{
#ifdef IEEEFP
- register int32_t *i32p;
+ int32_t *i32p;
bool_t rv;
- long tmpl;
#else
- register long *lp;
+ int32_t *lp;
struct ieee_double id;
struct vax_double vd;
- register struct dbl_limits *lim;
+ struct dbl_limits *lim;
int i;
#endif
@@ -220,21 +222,17 @@ xdr_double(xdrs, dp)
case XDR_ENCODE:
#ifdef IEEEFP
- i32p = (int32_t *)dp;
+ i32p = (int32_t *)(void *)dp;
#if BYTE_ORDER == BIG_ENDIAN
- tmpl = *i32p++;
- rv = XDR_PUTLONG(xdrs, &tmpl);
+ rv = XDR_PUTINT32(xdrs, i32p);
if (!rv)
return (rv);
- tmpl = *i32p;
- rv = XDR_PUTLONG(xdrs, &tmpl);
+ rv = XDR_PUTINT32(xdrs, i32p+1);
#else
- tmpl = *(i32p+1);
- rv = XDR_PUTLONG(xdrs, &tmpl);
+ rv = XDR_PUTINT32(xdrs, i32p+1);
if (!rv)
return (rv);
- tmpl = *i32p;
- rv = XDR_PUTLONG(xdrs, &tmpl);
+ rv = XDR_PUTINT32(xdrs, i32p);
#endif
return (rv);
#else
@@ -258,32 +256,28 @@ xdr_double(xdrs, dp)
((vd.mantissa4 >> 3) & MASK(13));
shipit:
id.sign = vd.sign;
- lp = (long *)&id;
- return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+ lp = (int32_t *)&id;
+ return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
#endif
case XDR_DECODE:
#ifdef IEEEFP
- i32p = (int32_t *)dp;
+ i32p = (int32_t *)(void *)dp;
#if BYTE_ORDER == BIG_ENDIAN
- rv = XDR_GETLONG(xdrs, &tmpl);
- *i32p++ = tmpl;
+ rv = XDR_GETINT32(xdrs, i32p);
if (!rv)
return (rv);
- rv = XDR_GETLONG(xdrs, &tmpl);
- *i32p = tmpl;
+ rv = XDR_GETINT32(xdrs, i32p+1);
#else
- rv = XDR_GETLONG(xdrs, &tmpl);
- *(i32p+1) = tmpl;
+ rv = XDR_GETINT32(xdrs, i32p+1);
if (!rv)
return (rv);
- rv = XDR_GETLONG(xdrs, &tmpl);
- *i32p = tmpl;
+ rv = XDR_GETINT32(xdrs, i32p);
#endif
return (rv);
#else
- lp = (long *)&id;
- if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+ lp = (int32_t *)&id;
+ if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
return (FALSE);
for (i = 0, lim = dbl_limits;
i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
@@ -310,5 +304,6 @@ xdr_double(xdrs, dp)
case XDR_FREE:
return (TRUE);
}
+ /* NOTREACHED */
return (FALSE);
}
diff --git a/lib/libc/xdr/xdr_mem.c b/lib/libc/xdr/xdr_mem.c
index 3193e64939dd..b54fc59c0a43 100644
--- a/lib/libc/xdr/xdr_mem.c
+++ b/lib/libc/xdr/xdr_mem.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
@@ -44,24 +47,31 @@ static char *rcsid = "$FreeBSD$";
*
*/
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <netinet/in.h>
+
#include <string.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
-#include <netinet/in.h>
-
-static bool_t xdrmem_getlong_aligned();
-static bool_t xdrmem_putlong_aligned();
-static bool_t xdrmem_getlong_unaligned();
-static bool_t xdrmem_putlong_unaligned();
-static bool_t xdrmem_getbytes();
-static bool_t xdrmem_putbytes();
-static u_int xdrmem_getpos(); /* XXX w/64-bit pointers, u_int not enough! */
-static bool_t xdrmem_setpos();
-static int32_t *xdrmem_inline_aligned();
-static int32_t *xdrmem_inline_unaligned();
-static void xdrmem_destroy();
-
-static struct xdr_ops xdrmem_ops_aligned = {
+#include "un-namespace.h"
+
+static void xdrmem_destroy __P((XDR *));
+static bool_t xdrmem_getlong_aligned __P((XDR *, long *));
+static bool_t xdrmem_putlong_aligned __P((XDR *, const long *));
+static bool_t xdrmem_getlong_unaligned __P((XDR *, long *));
+static bool_t xdrmem_putlong_unaligned __P((XDR *, const long *));
+static bool_t xdrmem_getbytes __P((XDR *, char *, u_int));
+static bool_t xdrmem_putbytes __P((XDR *, const char *, u_int));
+/* XXX: w/64-bit pointers, u_int not enough! */
+static u_int xdrmem_getpos __P((XDR *));
+static bool_t xdrmem_setpos __P((XDR *, u_int));
+static int32_t *xdrmem_inline_aligned __P((XDR *, u_int));
+static int32_t *xdrmem_inline_unaligned __P((XDR *, u_int));
+
+static const struct xdr_ops xdrmem_ops_aligned = {
xdrmem_getlong_aligned,
xdrmem_putlong_aligned,
xdrmem_getbytes,
@@ -72,7 +82,7 @@ static struct xdr_ops xdrmem_ops_aligned = {
xdrmem_destroy
};
-static struct xdr_ops xdrmem_ops_unaligned = {
+static const struct xdr_ops xdrmem_ops_unaligned = {
xdrmem_getlong_unaligned,
xdrmem_putlong_unaligned,
xdrmem_getbytes,
@@ -89,154 +99,156 @@ static struct xdr_ops xdrmem_ops_unaligned = {
*/
void
xdrmem_create(xdrs, addr, size, op)
- register XDR *xdrs;
- caddr_t addr;
+ XDR *xdrs;
+ char *addr;
u_int size;
enum xdr_op op;
{
xdrs->x_op = op;
- xdrs->x_ops = ((size_t)addr & (sizeof(int32_t) - 1))
- ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
+ xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1))
+ ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
xdrs->x_private = xdrs->x_base = addr;
xdrs->x_handy = size;
}
+/*ARGSUSED*/
static void
-xdrmem_destroy(/*xdrs*/)
- /*XDR *xdrs;*/
+xdrmem_destroy(xdrs)
+ XDR *xdrs;
{
}
static bool_t
xdrmem_getlong_aligned(xdrs, lp)
- register XDR *xdrs;
+ XDR *xdrs;
long *lp;
{
if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
return (FALSE);
- *lp = ntohl(*(int32_t *)(xdrs->x_private));
- xdrs->x_private += sizeof(int32_t);
+ *lp = ntohl(*(u_int32_t *)xdrs->x_private);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
return (TRUE);
}
static bool_t
xdrmem_putlong_aligned(xdrs, lp)
- register XDR *xdrs;
- long *lp;
+ XDR *xdrs;
+ const long *lp;
{
if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
return (FALSE);
- *(int32_t *)xdrs->x_private = htonl(*lp);
- xdrs->x_private += sizeof(int32_t);
+ *(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
return (TRUE);
}
static bool_t
xdrmem_getlong_unaligned(xdrs, lp)
- register XDR *xdrs;
+ XDR *xdrs;
long *lp;
{
- int32_t l;
+ u_int32_t l;
if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
return (FALSE);
- memcpy(&l, xdrs->x_private, sizeof(int32_t));
+ memmove(&l, xdrs->x_private, sizeof(int32_t));
*lp = ntohl(l);
- xdrs->x_private += sizeof(int32_t);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
return (TRUE);
}
static bool_t
xdrmem_putlong_unaligned(xdrs, lp)
- register XDR *xdrs;
- long *lp;
+ XDR *xdrs;
+ const long *lp;
{
- int32_t l;
+ u_int32_t l;
if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
return (FALSE);
- l = htonl(*lp);
- memcpy(xdrs->x_private, &l, sizeof(int32_t));
- xdrs->x_private += sizeof(int32_t);
+ l = htonl((u_int32_t)*lp);
+ memmove(xdrs->x_private, &l, sizeof(int32_t));
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
return (TRUE);
}
static bool_t
xdrmem_getbytes(xdrs, addr, len)
- register XDR *xdrs;
- caddr_t addr;
- register u_int len;
+ XDR *xdrs;
+ char *addr;
+ u_int len;
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
- memcpy(addr, xdrs->x_private, len);
- xdrs->x_private += len;
+ memmove(addr, xdrs->x_private, len);
+ xdrs->x_private = (char *)xdrs->x_private + len;
return (TRUE);
}
static bool_t
xdrmem_putbytes(xdrs, addr, len)
- register XDR *xdrs;
- caddr_t addr;
- register u_int len;
+ XDR *xdrs;
+ const char *addr;
+ u_int len;
{
if ((xdrs->x_handy -= len) < 0)
return (FALSE);
- memcpy(xdrs->x_private, addr, len);
- xdrs->x_private += len;
+ memmove(xdrs->x_private, addr, len);
+ xdrs->x_private = (char *)xdrs->x_private + len;
return (TRUE);
}
static u_int
xdrmem_getpos(xdrs)
- register XDR *xdrs;
+ XDR *xdrs;
{
/* XXX w/64-bit pointers, u_int not enough! */
- return ((u_long)xdrs->x_private - (u_long)xdrs->x_base);
+ return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base);
}
static bool_t
xdrmem_setpos(xdrs, pos)
- register XDR *xdrs;
+ XDR *xdrs;
u_int pos;
{
- register caddr_t newaddr = xdrs->x_base + pos;
- register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+ char *newaddr = xdrs->x_base + pos;
+ char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy;
if ((long)newaddr > (long)lastaddr)
return (FALSE);
xdrs->x_private = newaddr;
- xdrs->x_handy = (long)lastaddr - (long)newaddr;
+ xdrs->x_handy = (int)((long)lastaddr - (long)newaddr);
return (TRUE);
}
static int32_t *
xdrmem_inline_aligned(xdrs, len)
- register XDR *xdrs;
- int len;
+ XDR *xdrs;
+ u_int len;
{
int32_t *buf = 0;
if (xdrs->x_handy >= len) {
xdrs->x_handy -= len;
- buf = (int32_t *) xdrs->x_private;
- xdrs->x_private += len;
+ buf = (int32_t *)xdrs->x_private;
+ xdrs->x_private = (char *)xdrs->x_private + len;
}
return (buf);
}
+/* ARGSUSED */
static int32_t *
xdrmem_inline_unaligned(xdrs, len)
- register XDR *xdrs;
- int len;
+ XDR *xdrs;
+ u_int len;
{
-
+
return (0);
}
diff --git a/lib/libc/xdr/xdr_rec.c b/lib/libc/xdr/xdr_rec.c
index 7136463df545..616dbf618871 100644
--- a/lib/libc/xdr/xdr_rec.c
+++ b/lib/libc/xdr/xdr_rec.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -26,7 +28,9 @@
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
-#if defined(LIBC_SCCS) && !defined(lint)
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
@@ -45,33 +49,35 @@ static char *rcsid = "$FreeBSD$";
* by n bytes of data, where n is contained in the header. The header
* is represented as a htonl(u_long). Thegh order bit encodes
* whether or not the fragment is the last fragment of the record
- * (1 => fragment is last, 0 => more fragments to follow.
+ * (1 => fragment is last, 0 => more fragments to follow.
* The other 31 bits encode the byte length of the fragment.
*/
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
-#include <netinet/in.h>
+#include "un-namespace.h"
-static u_int fix_buf_size();
-static bool_t flush_out();
-static bool_t get_input_bytes();
-static bool_t set_input_fragment();
-static bool_t skip_input_bytes();
-
-static bool_t xdrrec_getlong();
-static bool_t xdrrec_putlong();
-static bool_t xdrrec_getbytes();
-static bool_t xdrrec_putbytes();
-static u_int xdrrec_getpos();
-static bool_t xdrrec_setpos();
-static int32_t *xdrrec_inline();
-static void xdrrec_destroy();
-
-static struct xdr_ops xdrrec_ops = {
+static bool_t xdrrec_getlong __P((XDR *, long *));
+static bool_t xdrrec_putlong __P((XDR *, const long *));
+static bool_t xdrrec_getbytes __P((XDR *, char *, u_int));
+
+static bool_t xdrrec_putbytes __P((XDR *, const char *, u_int));
+static u_int xdrrec_getpos __P((XDR *));
+static bool_t xdrrec_setpos __P((XDR *, u_int));
+static int32_t *xdrrec_inline __P((XDR *, u_int));
+static void xdrrec_destroy __P((XDR *));
+
+static const struct xdr_ops xdrrec_ops = {
xdrrec_getlong,
xdrrec_putlong,
xdrrec_getbytes,
@@ -98,31 +104,38 @@ static struct xdr_ops xdrrec_ops = {
#define LAST_FRAG ((u_int32_t)(1 << 31))
typedef struct rec_strm {
- caddr_t tcp_handle;
- caddr_t the_buffer;
+ char *tcp_handle;
+ char *the_buffer;
/*
* out-goung bits
*/
- int (*writeit) __P((caddr_t, caddr_t, int));
- caddr_t out_base; /* output buffer (points to frag header) */
- caddr_t out_finger; /* next output position */
- caddr_t out_boundry; /* data cannot up to this address */
- u_int32_t *frag_header; /* beginning of current fragment */
+ int (*writeit) __P((char *, char *, int));
+ char *out_base; /* output buffer (points to frag header) */
+ char *out_finger; /* next output position */
+ char *out_boundry; /* data cannot up to this address */
+ u_int32_t *frag_header; /* beginning of curren fragment */
bool_t frag_sent; /* true if buffer sent in middle of record */
/*
* in-coming bits
*/
- int (*readit) __P((caddr_t, caddr_t, int));
+ int (*readit) __P((char *, char *, int));
u_long in_size; /* fixed size of the input buffer */
- caddr_t in_base;
- caddr_t in_finger; /* location of next byte to be had */
- caddr_t in_boundry; /* can read up to this location */
+ char *in_base;
+ char *in_finger; /* location of next byte to be had */
+ char *in_boundry; /* can read up to this location */
long fbtbc; /* fragment bytes to be consumed */
bool_t last_frag;
u_int sendsize;
u_int recvsize;
} RECSTREAM;
+static u_int fix_buf_size __P((u_int));
+static bool_t flush_out __P((RECSTREAM *, bool_t));
+static bool_t fill_input_buf __P((RECSTREAM *));
+static bool_t get_input_bytes __P((RECSTREAM *, char *, int));
+static bool_t set_input_fragment __P((RECSTREAM *));
+static bool_t skip_input_bytes __P((RECSTREAM *, long));
+
/*
* Create an xdr handle for xdrrec
@@ -135,20 +148,21 @@ typedef struct rec_strm {
*/
void
xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
- register XDR *xdrs;
- register u_int sendsize;
- register u_int recvsize;
- caddr_t tcp_handle;
- int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
- int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
+ XDR *xdrs;
+ u_int sendsize;
+ u_int recvsize;
+ char *tcp_handle;
+ /* like read, but pass it a tcp_handle, not sock */
+ int (*readit) __P((char *, char *, int));
+ /* like write, but pass it a tcp_handle, not sock */
+ int (*writeit) __P((char *, char *, int));
{
- register RECSTREAM *rstrm =
- (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+ RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
if (rstrm == NULL) {
- (void)fprintf(stderr, "xdrrec_create: out of memory\n");
- /*
- * This is bad. Should rework xdrrec_create to
+ warnx("xdrrec_create: out of memory");
+ /*
+ * This is bad. Should rework xdrrec_create to
* return a handle, and in this case return NULL
*/
return;
@@ -160,7 +174,7 @@ xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
rstrm->recvsize = recvsize = fix_buf_size(recvsize);
rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
if (rstrm->the_buffer == NULL) {
- (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ warnx("xdrrec_create: out of memory");
return;
}
for (rstrm->out_base = rstrm->the_buffer;
@@ -171,12 +185,12 @@ xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
* now the rest ...
*/
xdrs->x_ops = &xdrrec_ops;
- xdrs->x_private = (caddr_t)rstrm;
+ xdrs->x_private = rstrm;
rstrm->tcp_handle = tcp_handle;
rstrm->readit = readit;
rstrm->writeit = writeit;
rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
- rstrm->frag_header = (u_int32_t *)rstrm->out_base;
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
rstrm->out_finger += sizeof(u_int32_t);
rstrm->out_boundry += sendsize;
rstrm->frag_sent = FALSE;
@@ -198,8 +212,8 @@ xdrrec_getlong(xdrs, lp)
XDR *xdrs;
long *lp;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
- register int32_t *buflp = (int32_t *)(rstrm->in_finger);
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
int32_t mylong;
/* first try the inline, fast case */
@@ -209,7 +223,8 @@ xdrrec_getlong(xdrs, lp)
rstrm->fbtbc -= sizeof(int32_t);
rstrm->in_finger += sizeof(int32_t);
} else {
- if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(int32_t)))
+ if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
+ sizeof(int32_t)))
return (FALSE);
*lp = (long)ntohl((u_int32_t)mylong);
}
@@ -219,10 +234,10 @@ xdrrec_getlong(xdrs, lp)
static bool_t
xdrrec_putlong(xdrs, lp)
XDR *xdrs;
- long *lp;
+ const long *lp;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
- register int32_t *dest_lp = ((int32_t *)(rstrm->out_finger));
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
/*
@@ -233,7 +248,7 @@ xdrrec_putlong(xdrs, lp)
rstrm->frag_sent = TRUE;
if (! flush_out(rstrm, FALSE))
return (FALSE);
- dest_lp = ((int32_t *)(rstrm->out_finger));
+ dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
rstrm->out_finger += sizeof(int32_t);
}
*dest_lp = (int32_t)htonl((u_int32_t)(*lp));
@@ -243,14 +258,14 @@ xdrrec_putlong(xdrs, lp)
static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes(xdrs, addr, len)
XDR *xdrs;
- register caddr_t addr;
- register u_int len;
+ char *addr;
+ u_int len;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
- register int current;
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int current;
while (len > 0) {
- current = rstrm->fbtbc;
+ current = (int)rstrm->fbtbc;
if (current == 0) {
if (rstrm->last_frag)
return (FALSE);
@@ -261,7 +276,7 @@ xdrrec_getbytes(xdrs, addr, len)
current = (len < current) ? len : current;
if (! get_input_bytes(rstrm, addr, current))
return (FALSE);
- addr += current;
+ addr += current;
rstrm->fbtbc -= current;
len -= current;
}
@@ -271,17 +286,17 @@ xdrrec_getbytes(xdrs, addr, len)
static bool_t
xdrrec_putbytes(xdrs, addr, len)
XDR *xdrs;
- register caddr_t addr;
- register u_int len;
+ const char *addr;
+ u_int len;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
- register long current;
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ size_t current;
while (len > 0) {
- current = (u_long)rstrm->out_boundry -
- (u_long)rstrm->out_finger;
+ current = (size_t)((u_long)rstrm->out_boundry -
+ (u_long)rstrm->out_finger);
current = (len < current) ? len : current;
- memcpy(rstrm->out_finger, addr, current);
+ memmove(rstrm->out_finger, addr, current);
rstrm->out_finger += current;
addr += current;
len -= current;
@@ -296,12 +311,12 @@ xdrrec_putbytes(xdrs, addr, len)
static u_int
xdrrec_getpos(xdrs)
- register XDR *xdrs;
+ XDR *xdrs;
{
- register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
- register long pos;
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ off_t pos;
- pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1);
+ pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1);
if (pos != -1)
switch (xdrs->x_op) {
@@ -314,7 +329,7 @@ xdrrec_getpos(xdrs)
break;
default:
- pos = -1;
+ pos = (off_t) -1;
break;
}
return ((u_int) pos);
@@ -322,20 +337,20 @@ xdrrec_getpos(xdrs)
static bool_t
xdrrec_setpos(xdrs, pos)
- register XDR *xdrs;
+ XDR *xdrs;
u_int pos;
{
- register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
u_int currpos = xdrrec_getpos(xdrs);
int delta = currpos - pos;
- caddr_t newpos;
+ char *newpos;
if ((int)currpos != -1)
switch (xdrs->x_op) {
case XDR_ENCODE:
newpos = rstrm->out_finger - delta;
- if ((newpos > (caddr_t)(rstrm->frag_header)) &&
+ if ((newpos > (char *)(void *)(rstrm->frag_header)) &&
(newpos < rstrm->out_boundry)) {
rstrm->out_finger = newpos;
return (TRUE);
@@ -352,23 +367,26 @@ xdrrec_setpos(xdrs, pos)
return (TRUE);
}
break;
+
+ case XDR_FREE:
+ break;
}
return (FALSE);
}
static int32_t *
xdrrec_inline(xdrs, len)
- register XDR *xdrs;
- int len;
+ XDR *xdrs;
+ u_int len;
{
- register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
- int32_t * buf = NULL;
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ int32_t *buf = NULL;
switch (xdrs->x_op) {
case XDR_ENCODE:
if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
- buf = (int32_t *) rstrm->out_finger;
+ buf = (int32_t *)(void *)rstrm->out_finger;
rstrm->out_finger += len;
}
break;
@@ -376,24 +394,27 @@ xdrrec_inline(xdrs, len)
case XDR_DECODE:
if ((len <= rstrm->fbtbc) &&
((rstrm->in_finger + len) <= rstrm->in_boundry)) {
- buf = (int32_t *) rstrm->in_finger;
+ buf = (int32_t *)(void *)rstrm->in_finger;
rstrm->fbtbc -= len;
rstrm->in_finger += len;
}
break;
+
+ case XDR_FREE:
+ break;
}
return (buf);
}
static void
xdrrec_destroy(xdrs)
- register XDR *xdrs;
+ XDR *xdrs;
{
- register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
mem_free(rstrm->the_buffer,
rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
- mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
+ mem_free(rstrm, sizeof(RECSTREAM));
}
@@ -409,7 +430,7 @@ bool_t
xdrrec_skiprecord(xdrs)
XDR *xdrs;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
if (! skip_input_bytes(rstrm, rstrm->fbtbc))
@@ -423,7 +444,7 @@ xdrrec_skiprecord(xdrs)
}
/*
- * Look ahead fuction.
+ * Look ahead function.
* Returns TRUE iff there is no more input in the buffer
* after consuming the rest of the current record.
*/
@@ -431,7 +452,7 @@ bool_t
xdrrec_eof(xdrs)
XDR *xdrs;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
if (! skip_input_bytes(rstrm, rstrm->fbtbc))
@@ -456,8 +477,8 @@ xdrrec_endofrecord(xdrs, sendnow)
XDR *xdrs;
bool_t sendnow;
{
- register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
- register u_long len; /* fragment length */
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ u_long len; /* fragment length */
if (sendnow || rstrm->frag_sent ||
((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
@@ -467,8 +488,8 @@ xdrrec_endofrecord(xdrs, sendnow)
}
len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
sizeof(u_int32_t);
- *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
- rstrm->frag_header = (u_int32_t *)rstrm->out_finger;
+ *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG);
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger;
rstrm->out_finger += sizeof(u_int32_t);
return (TRUE);
}
@@ -479,35 +500,36 @@ xdrrec_endofrecord(xdrs, sendnow)
*/
static bool_t
flush_out(rstrm, eor)
- register RECSTREAM *rstrm;
+ RECSTREAM *rstrm;
bool_t eor;
{
- register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
- register u_int32_t len = (u_long)(rstrm->out_finger) -
- (u_long)(rstrm->frag_header) - sizeof(u_int32_t);
+ u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->frag_header) - sizeof(u_int32_t));
*(rstrm->frag_header) = htonl(len | eormask);
- len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
+ len = (u_int32_t)((u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->out_base));
if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
!= (int)len)
return (FALSE);
- rstrm->frag_header = (u_int32_t *)rstrm->out_base;
- rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_int32_t);
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
+ rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t);
return (TRUE);
}
static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf(rstrm)
- register RECSTREAM *rstrm;
+ RECSTREAM *rstrm;
{
- register caddr_t where;
- u_long i;
- register long len;
+ char *where;
+ u_int32_t i;
+ int len;
where = rstrm->in_base;
- i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+ i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
where += i;
- len = rstrm->in_size - i;
+ len = (u_int32_t)(rstrm->in_size - i);
if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
return (FALSE);
rstrm->in_finger = where;
@@ -518,21 +540,22 @@ fill_input_buf(rstrm)
static bool_t /* knows nothing about records! Only about input buffers */
get_input_bytes(rstrm, addr, len)
- register RECSTREAM *rstrm;
- register caddr_t addr;
- register int len;
+ RECSTREAM *rstrm;
+ char *addr;
+ int len;
{
- register long current;
+ size_t current;
while (len > 0) {
- current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ current = (size_t)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
if (current == 0) {
if (! fill_input_buf(rstrm))
return (FALSE);
continue;
}
current = (len < current) ? len : current;
- memcpy(addr, rstrm->in_finger, current);
+ memmove(addr, rstrm->in_finger, current);
rstrm->in_finger += current;
addr += current;
len -= current;
@@ -542,13 +565,13 @@ get_input_bytes(rstrm, addr, len)
static bool_t /* next two bytes of the input stream are treated as a header */
set_input_fragment(rstrm)
- register RECSTREAM *rstrm;
+ RECSTREAM *rstrm;
{
u_int32_t header;
- if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header)))
return (FALSE);
- header = (long)ntohl(header);
+ header = ntohl(header);
rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
/*
* Sanity check. Try not to accept wildly incorrect
@@ -566,19 +589,20 @@ set_input_fragment(rstrm)
static bool_t /* consumes input bytes; knows nothing about records! */
skip_input_bytes(rstrm, cnt)
- register RECSTREAM *rstrm;
+ RECSTREAM *rstrm;
long cnt;
{
- register long current;
+ u_int32_t current;
while (cnt > 0) {
- current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ current = (size_t)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
if (current == 0) {
if (! fill_input_buf(rstrm))
return (FALSE);
continue;
}
- current = (cnt < current) ? cnt : current;
+ current = (u_int32_t)((cnt < current) ? cnt : current);
rstrm->in_finger += current;
cnt -= current;
}
@@ -587,7 +611,7 @@ skip_input_bytes(rstrm, cnt)
static u_int
fix_buf_size(s)
- register u_int s;
+ u_int s;
{
if (s < 100)
diff --git a/lib/libc/xdr/xdr_reference.c b/lib/libc/xdr/xdr_reference.c
index b0cdbce93008..60e7020413ef 100644
--- a/lib/libc/xdr/xdr_reference.c
+++ b/lib/libc/xdr/xdr_reference.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_reference.c,v 1.13 2000/01/22 22:19:18 mycroft Exp $
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,7 +29,8 @@
* Mountain View, California 94043
*/
-#if defined(LIBC_SCCS) && !defined(lint)
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$FreeBSD$";
@@ -42,13 +45,15 @@ static char *rcsid = "$FreeBSD$";
* "pointers". See xdr.h for more info on the interface to xdr.
*/
+#include "namespace.h"
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
-
-#define LASTUNSIGNED ((u_int) 0-1)
+#include "libc_private.h"
/*
* XDR an indirect pointer
@@ -61,13 +66,13 @@ static char *rcsid = "$FreeBSD$";
*/
bool_t
xdr_reference(xdrs, pp, size, proc)
- register XDR *xdrs;
+ XDR *xdrs;
caddr_t *pp; /* the pointer to work on */
u_int size; /* size of the object pointed to */
xdrproc_t proc; /* xdr routine to handle the object */
{
- register caddr_t loc = *pp;
- register bool_t stat;
+ caddr_t loc = *pp;
+ bool_t stat;
if (loc == NULL)
switch (xdrs->x_op) {
@@ -77,15 +82,17 @@ xdr_reference(xdrs, pp, size, proc)
case XDR_DECODE:
*pp = loc = (caddr_t) mem_alloc(size);
if (loc == NULL) {
- (void) fprintf(stderr,
- "xdr_reference: out of memory\n");
+ warnx("xdr_reference: out of memory");
return (FALSE);
}
- memset(loc, 0, (int)size);
+ memset(loc, 0, size);
break;
- }
- stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+ case XDR_ENCODE:
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc);
if (xdrs->x_op == XDR_FREE) {
mem_free(loc, size);
@@ -116,7 +123,7 @@ xdr_reference(xdrs, pp, size, proc)
*/
bool_t
xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
- register XDR *xdrs;
+ XDR *xdrs;
char **objpp;
u_int obj_size;
xdrproc_t xdr_obj;
diff --git a/lib/libc/xdr/xdr_sizeof.c b/lib/libc/xdr/xdr_sizeof.c
index 5a4c1a78dc08..f90cc344798d 100644
--- a/lib/libc/xdr/xdr_sizeof.c
+++ b/lib/libc/xdr/xdr_sizeof.c
@@ -1,4 +1,6 @@
/*
+ * $FreeBSD$
+ *
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
@@ -35,10 +37,12 @@
* when serialized using XDR.
*/
+#include "namespace.h"
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <sys/types.h>
#include <stdlib.h>
+#include "un-namespace.h"
/* ARGSUSED */
static bool_t
diff --git a/lib/libc/xdr/xdr_stdio.c b/lib/libc/xdr/xdr_stdio.c
index 708573ccdf58..c4328ec181a8 100644
--- a/lib/libc/xdr/xdr_stdio.c
+++ b/lib/libc/xdr/xdr_stdio.c
@@ -1,3 +1,5 @@
+/* $NetBSD: xdr_stdio.c,v 1.14 2000/01/22 22:19:19 mycroft Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,6 +29,7 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/
@@ -43,23 +46,26 @@ static char *rcsid = "$FreeBSD$";
* from the stream.
*/
-#include <rpc/types.h>
+#include "namespace.h"
#include <stdio.h>
+
+#include <rpc/types.h>
#include <rpc/xdr.h>
+#include "un-namespace.h"
-static bool_t xdrstdio_getlong();
-static bool_t xdrstdio_putlong();
-static bool_t xdrstdio_getbytes();
-static bool_t xdrstdio_putbytes();
-static u_int xdrstdio_getpos();
-static bool_t xdrstdio_setpos();
-static int32_t *xdrstdio_inline();
-static void xdrstdio_destroy();
+static void xdrstdio_destroy __P((XDR *));
+static bool_t xdrstdio_getlong __P((XDR *, long *));
+static bool_t xdrstdio_putlong __P((XDR *, const long *));
+static bool_t xdrstdio_getbytes __P((XDR *, char *, u_int));
+static bool_t xdrstdio_putbytes __P((XDR *, const char *, u_int));
+static u_int xdrstdio_getpos __P((XDR *));
+static bool_t xdrstdio_setpos __P((XDR *, u_int));
+static int32_t *xdrstdio_inline __P((XDR *, u_int));
/*
* Ops vector for stdio type XDR
*/
-static struct xdr_ops xdrstdio_ops = {
+static const struct xdr_ops xdrstdio_ops = {
xdrstdio_getlong, /* deseraialize a long int */
xdrstdio_putlong, /* seraialize a long int */
xdrstdio_getbytes, /* deserialize counted bytes */
@@ -77,14 +83,14 @@ static struct xdr_ops xdrstdio_ops = {
*/
void
xdrstdio_create(xdrs, file, op)
- register XDR *xdrs;
+ XDR *xdrs;
FILE *file;
enum xdr_op op;
{
xdrs->x_op = op;
xdrs->x_ops = &xdrstdio_ops;
- xdrs->x_private = (caddr_t)file;
+ xdrs->x_private = file;
xdrs->x_handy = 0;
xdrs->x_base = 0;
}
@@ -95,35 +101,32 @@ xdrstdio_create(xdrs, file, op)
*/
static void
xdrstdio_destroy(xdrs)
- register XDR *xdrs;
+ XDR *xdrs;
{
(void)fflush((FILE *)xdrs->x_private);
- /* xx should we close the file ?? */
+ /* XXX: should we close the file ?? */
}
static bool_t
xdrstdio_getlong(xdrs, lp)
XDR *xdrs;
- register long *lp;
+ long *lp;
{
- if (fread((caddr_t)lp, sizeof(int32_t), 1,
- (FILE *)xdrs->x_private) != 1)
+ if (fread(lp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
return (FALSE);
- *lp = (long)ntohl((int32_t)*lp);
+ *lp = (long)ntohl((u_int32_t)*lp);
return (TRUE);
}
static bool_t
xdrstdio_putlong(xdrs, lp)
XDR *xdrs;
- long *lp;
+ const long *lp;
{
+ long mycopy = (long)htonl((u_int32_t)*lp);
- long mycopy = (long)htonl((int32_t)*lp);
-
- if (fwrite((caddr_t)&mycopy, sizeof(int32_t), 1,
- (FILE *)xdrs->x_private) != 1)
+ if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
return (FALSE);
return (TRUE);
}
@@ -131,11 +134,11 @@ xdrstdio_putlong(xdrs, lp)
static bool_t
xdrstdio_getbytes(xdrs, addr, len)
XDR *xdrs;
- caddr_t addr;
+ char *addr;
u_int len;
{
- if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1))
return (FALSE);
return (TRUE);
}
@@ -143,11 +146,12 @@ xdrstdio_getbytes(xdrs, addr, len)
static bool_t
xdrstdio_putbytes(xdrs, addr, len)
XDR *xdrs;
- caddr_t addr;
+ const char *addr;
u_int len;
{
- if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ if ((len != 0) && (fwrite(addr, (size_t)len, 1,
+ (FILE *)xdrs->x_private) != 1))
return (FALSE);
return (TRUE);
}
@@ -161,15 +165,16 @@ xdrstdio_getpos(xdrs)
}
static bool_t
-xdrstdio_setpos(xdrs, pos)
+xdrstdio_setpos(xdrs, pos)
XDR *xdrs;
u_int pos;
-{
+{
return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
FALSE : TRUE);
}
+/* ARGSUSED */
static int32_t *
xdrstdio_inline(xdrs, len)
XDR *xdrs;
diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc
index fe19b0e081d3..cf9e154df50d 100644
--- a/lib/libc_r/uthread/Makefile.inc
+++ b/lib/libc_r/uthread/Makefile.inc
@@ -69,6 +69,7 @@ SRCS+= \
uthread_kevent.c \
uthread_kill.c \
uthread_listen.c \
+ uthread_main_np.c \
uthread_mattr_init.c \
uthread_mattr_kind_np.c \
uthread_msync.c \
diff --git a/usr.sbin/portmap/pmap_check.h b/lib/libc_r/uthread/uthread_main_np.c
index dc454a59d6d0..1ce336998f59 100644
--- a/usr.sbin/portmap/pmap_check.h
+++ b/lib/libc_r/uthread/uthread_main_np.c
@@ -1,5 +1,6 @@
-/*-
- * Copyright (c) 2000 Brian Somers <brian@Awfulhak.org>
+/*
+ * Copyright (c) 2001 Alfred Perlstein
+ * Author: Alfred Perlstein <alfred@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,19 +24,22 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) pmap_check.h 1.3 93/11/21 16:18:53
- *
- * $FreeBSD$
+ * $FreeBSD$
*/
-extern int from_local __P((struct sockaddr_in *));
-extern void check_startup __P((void));
-extern int check_default __P((struct sockaddr_in *, u_long, u_long));
-extern int check_setunset __P((struct sockaddr_in *, u_long, u_long, u_long));
-extern int check_privileged_port __P((struct sockaddr_in *, u_long, u_long,
- u_long));
-extern int check_callit __P((struct sockaddr_in *, u_long, u_long, u_long));
+#include <pthread.h>
+#include <pthread_np.h>
+#include "pthread_private.h"
+
+/*
+ * Provide the equivelant to Solaris thr_main() function
+ */
+int
+pthread_main_np()
+{
-extern int verboselog;
-extern int allow_severity;
-extern int deny_severity;
+ if (!_thread_initial)
+ return (-1);
+ else
+ return (pthread_equal(pthread_self(), _thread_initial) ? 1 : 0);
+}
diff --git a/lib/libkse/thread/Makefile.inc b/lib/libkse/thread/Makefile.inc
index fe19b0e081d3..cf9e154df50d 100644
--- a/lib/libkse/thread/Makefile.inc
+++ b/lib/libkse/thread/Makefile.inc
@@ -69,6 +69,7 @@ SRCS+= \
uthread_kevent.c \
uthread_kill.c \
uthread_listen.c \
+ uthread_main_np.c \
uthread_mattr_init.c \
uthread_mattr_kind_np.c \
uthread_msync.c \
diff --git a/lib/libkse/thread/thr_main_np.c b/lib/libkse/thread/thr_main_np.c
new file mode 100644
index 000000000000..1ce336998f59
--- /dev/null
+++ b/lib/libkse/thread/thr_main_np.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001 Alfred Perlstein
+ * Author: Alfred Perlstein <alfred@FreeBSD.org>
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <pthread.h>
+#include <pthread_np.h>
+#include "pthread_private.h"
+
+/*
+ * Provide the equivelant to Solaris thr_main() function
+ */
+int
+pthread_main_np()
+{
+
+ if (!_thread_initial)
+ return (-1);
+ else
+ return (pthread_equal(pthread_self(), _thread_initial) ? 1 : 0);
+}
diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc
index fe19b0e081d3..cf9e154df50d 100644
--- a/lib/libpthread/thread/Makefile.inc
+++ b/lib/libpthread/thread/Makefile.inc
@@ -69,6 +69,7 @@ SRCS+= \
uthread_kevent.c \
uthread_kill.c \
uthread_listen.c \
+ uthread_main_np.c \
uthread_mattr_init.c \
uthread_mattr_kind_np.c \
uthread_msync.c \
diff --git a/lib/libpthread/thread/thr_main_np.c b/lib/libpthread/thread/thr_main_np.c
new file mode 100644
index 000000000000..1ce336998f59
--- /dev/null
+++ b/lib/libpthread/thread/thr_main_np.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001 Alfred Perlstein
+ * Author: Alfred Perlstein <alfred@FreeBSD.org>
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <pthread.h>
+#include <pthread_np.h>
+#include "pthread_private.h"
+
+/*
+ * Provide the equivelant to Solaris thr_main() function
+ */
+int
+pthread_main_np()
+{
+
+ if (!_thread_initial)
+ return (-1);
+ else
+ return (pthread_equal(pthread_self(), _thread_initial) ? 1 : 0);
+}
diff --git a/lib/librpcsvc/Makefile b/lib/librpcsvc/Makefile
index 077a33eadc69..d6f319de9169 100644
--- a/lib/librpcsvc/Makefile
+++ b/lib/librpcsvc/Makefile
@@ -12,7 +12,7 @@ RPCSRCS= klm_prot.x mount.x nfs_prot.x nlm_prot.x rex.x rnusers.x \
OTHERSRCS= rnusers.c rstat.c rwall.c yp_passwd.c yp_update.c
SECRPCSRCS= secretkey.c xcrypt.c
-RPCCOM = rpcgen -C
+RPCCOM = rpcgen -CM
INCDIRS= -I${DESTDIR}/usr/include/rpcsvc -I${DESTDIR}/usr/include
diff --git a/lib/librpcsvc/yp_passwd.c b/lib/librpcsvc/yp_passwd.c
index f3d42b7154d8..26104fb2e752 100644
--- a/lib/librpcsvc/yp_passwd.c
+++ b/lib/librpcsvc/yp_passwd.c
@@ -80,7 +80,7 @@ int _yppasswd(oldpass, newpw)
}
rval = callrpc(server, YPPASSWDPROG, YPPASSWDVERS, YPPASSWDPROC_UPDATE,
- xdr_yppasswd, (char *)&yppasswd, xdr_int, &result);
+ xdr_yppasswd, (char *)&yppasswd, xdr_int, (char *)&result);
free(server);
if (rval || result)
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index 41873cace7a7..c1d746616901 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -50,6 +50,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syslog.h>
@@ -72,6 +73,7 @@ static const char rcsid[] =
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
@@ -193,7 +195,7 @@ NFSKERBKEYSCHED_T kerb_keysched;
#endif
int getnfsargs __P((char *, struct nfs_args *));
-void set_rpc_maxgrouplist __P((int));
+/* void set_rpc_maxgrouplist __P((int)); */
void usage __P((void)) __dead2;
int xdr_dir __P((XDR *, char *));
int xdr_fh __P((XDR *, struct nfhret *));
@@ -299,16 +301,16 @@ main(argc, argv)
case 'd':
nfsargsp->flags |= NFSMNT_DUMBTIMR;
break;
+#if 0 /* XXXX */
case 'g':
num = strtol(optarg, &p, 10);
if (*p || num <= 0)
errx(1, "illegal -g value -- %s", optarg);
-#ifdef __FreeBSD__
set_rpc_maxgrouplist(num);
-#endif
nfsargsp->maxgrouplist = num;
nfsargsp->flags |= NFSMNT_MAXGRPS;
break;
+#endif
case 'I':
num = strtol(optarg, &p, 10);
if (*p || num <= 0)
@@ -456,7 +458,6 @@ main(argc, argv)
/* resolve the mountpoint with realpath(3) */
(void)checkpath(name, mntpath);
-#ifdef __FreeBSD__
error = getvfsbyname("nfs", &vfc);
if (error && vfsisloadable("nfs")) {
if(vfsload("nfs"))
@@ -469,10 +470,6 @@ main(argc, argv)
if (mount(vfc.vfc_name, mntpath, mntflags, nfsargsp))
err(1, "%s", mntpath);
-#else
- if (mount("nfs", mntpath, mntflags, nfsargsp))
- err(1, "%s", mntpath);
-#endif
if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
if ((opflags & ISBGRND) == 0) {
if ((i = fork())) {
@@ -577,75 +574,32 @@ main(argc, argv)
exit(0);
}
-/*
- * Return RPC_SUCCESS if server responds.
- */
-enum clnt_stat
-pingnfsserver(addr, version, sotype)
- struct sockaddr_in *addr;
- int version;
- int sotype;
-{
- struct sockaddr_in sin;
- int tport;
- CLIENT *clp;
- int so = RPC_ANYSOCK;
- enum clnt_stat stat;
- struct timeval pertry, try;
-
- sin = *addr;
-
- if ((tport = port_no ? port_no :
- pmap_getport(&sin, RPCPROG_NFS, version, nfsproto)) == 0) {
- return rpc_createerr.cf_stat;
- }
-
- sin.sin_port = htons(tport);
-
- pertry.tv_sec = 10;
- pertry.tv_usec = 0;
- if (sotype == SOCK_STREAM)
- clp = clnttcp_create(&sin, RPCPROG_NFS, version,
- &so, 0, 0);
- else
- clp = clntudp_create(&sin, RPCPROG_NFS, version,
- pertry, &so);
- if (clp == NULL)
- return rpc_createerr.cf_stat;
-
- try.tv_sec = 10;
- try.tv_usec = 0;
- stat = clnt_call(clp, NFSPROC_NULL,
- xdr_void, NULL, xdr_void, NULL, try);
-
- clnt_destroy(clp);
-
- return stat;
-}
-
int
getnfsargs(spec, nfsargsp)
char *spec;
struct nfs_args *nfsargsp;
{
- register CLIENT *clp;
- struct hostent *hp;
- static struct sockaddr_in saddr;
+ CLIENT *clp;
+ struct addrinfo hints, *ai_nfs, *ai;
+ int ecode;
+ char host[NI_MAXHOST], serv[NI_MAXSERV];
+ static struct netbuf nfs_nb;
+ static struct sockaddr_storage nfs_ss;
+ struct netconfig *nconf;
+ char *netid;
struct timeval pertry, try;
enum clnt_stat clnt_stat;
- int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt, speclen;
+ int so, i, nfsvers, mntvers, orgcnt, speclen;
char *hostp, *delimp;
#ifdef NFSKERB
char *cp;
#endif
- u_short tport;
size_t len;
static struct nfhret nfhret;
static char nam[MNAMELEN + 1];
- tport = 0;
-
- if ((delimp = strchr(spec, ':')) != NULL) {
+ so = i = 0;
+ if ((delimp = strrchr(spec, ':')) != NULL) {
hostp = spec;
spec = delimp + 1;
} else if ((delimp = strrchr(spec, '@')) != NULL) {
@@ -684,27 +638,29 @@ getnfsargs(spec, nfsargsp)
* Handle an internet host address and reverse resolve it if
* doing Kerberos.
*/
- if (isdigit(*hostp)) {
- if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
- warnx("bad net address %s", hostp);
- return (0);
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = nfsargsp->sotype;
+ if (getaddrinfo(hostp, "nfs", &hints, &ai_nfs) == 0) {
+ if ((nfsargsp->flags & NFSMNT_KERB)) {
+ hints.ai_flags = 0;
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host,
+ sizeof host, serv, sizeof serv, 0) != 0) {
+ warnx("can't reverse resolve net address");
+ return (0);
+ }
+ hostp = host;
}
- } else if ((hp = gethostbyname(hostp)) != NULL)
- memmove(&saddr.sin_addr, hp->h_addr,
- MIN(hp->h_length, sizeof(saddr.sin_addr)));
- else {
- warnx("can't get net id for host");
- return (0);
- }
-#ifdef NFSKERB
- if ((nfsargsp->flags & NFSMNT_KERB)) {
- if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
- sizeof (u_long), AF_INET)) == (struct hostent *)0) {
- warnx("can't reverse resolve net address");
+ } else {
+ hints.ai_flags = 0;
+ if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
+ warnx("can't get net id for host/nfs: %s",
+ gai_strerror(ecode));
return (0);
}
- memmove(&saddr.sin_addr, hp->h_addr,
- MIN(hp->h_length, sizeof(saddr.sin_addr)));
+ }
+#ifdef NFSKERB
+ if (nfsargsp->flags & NFSMNT_KERB) {
strncpy(inst, hp->h_name, INST_SZ);
inst[INST_SZ - 1] = '\0';
if (cp = strchr(inst, '.'))
@@ -713,7 +669,7 @@ getnfsargs(spec, nfsargsp)
#endif /* NFSKERB */
orgcnt = retrycnt;
-tryagain:
+
if (mountmode == ANY || mountmode == V3) {
nfsvers = 3;
mntvers = 3;
@@ -724,103 +680,125 @@ tryagain:
nfsargsp->flags &= ~NFSMNT_NFSV3;
}
nfhret.stat = EACCES; /* Mark not yet successful */
- while (retrycnt > 0) {
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(PMAPPORT);
- if ((tport = port_no ? port_no :
- pmap_getport(&saddr, RPCPROG_NFS,
- nfsvers, nfsproto)) == 0) {
- if ((opflags & ISBGRND) == 0)
- clnt_pcreateerror("NFS Portmap");
+ ai = ai_nfs;
+ while (ai != NULL) {
+ /*
+ * XXX. Nead a generic (family, type, proto) -> nconf interface.
+ * __rpc_*2nconf exist, maybe they should be exported.
+ */
+ if (nfsargsp->sotype == SOCK_STREAM) {
+ if (ai->ai_family == AF_INET6)
+ netid = "tcp6";
+ else
+ netid = "tcp";
} else {
- /*
- * First ping the nfs server to see if it supports
- * the version of the protocol we want to use.
- */
- clnt_stat = pingnfsserver(&saddr, nfsvers,
- nfsargsp->sotype);
- if (clnt_stat == RPC_PROGVERSMISMATCH) {
- if (mountmode == ANY) {
- mountmode = V2;
- goto tryagain;
- } else {
- errx(1, "can't contact NFS server");
- }
- }
- saddr.sin_port = 0;
- pertry.tv_sec = 10;
- pertry.tv_usec = 0;
- if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
- clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
- &so, 0, 0);
+ if (ai->ai_family == AF_INET6)
+ netid = "udp6";
else
- clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
- pertry, &so);
- if (clp == NULL) {
+ netid = "udp";
+ }
+
+ nconf = getnetconfigent(netid);
+
+tryagain:
+ retrycnt = orgcnt;
+
+ while (retrycnt > 0) {
+ nfs_nb.buf = &nfs_ss;
+ nfs_nb.maxlen = sizeof nfs_ss;
+ if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf,
+ &nfs_nb, hostp)){
+ if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) {
+ nfhret.stat = rpc_createerr.cf_error.re_errno;
+ break;
+ }
+ if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) {
+ nfhret.stat = EPROTONOSUPPORT;
+ break;
+ }
if ((opflags & ISBGRND) == 0)
- clnt_pcreateerror("Cannot MNT RPC");
+ clnt_pcreateerror(
+ "mount_nfs: rpcbind on server");
} else {
- clp->cl_auth = authunix_create_default();
- try.tv_sec = 10;
- try.tv_usec = 0;
- if (nfsargsp->flags & NFSMNT_KERB)
- nfhret.auth = RPCAUTH_KERB4;
- else
- nfhret.auth = RPCAUTH_UNIX;
- nfhret.vers = mntvers;
- clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
- xdr_dir, spec, xdr_fh, &nfhret, try);
- if (clnt_stat != RPC_SUCCESS) {
- if (clnt_stat == RPC_PROGVERSMISMATCH) {
- if (mountmode == ANY) {
- mountmode = V2;
- goto tryagain;
- } else {
- errx(1, "%s",
- clnt_sperror(clp, "MNT RPC"));
- }
- }
+ pertry.tv_sec = 10;
+ pertry.tv_usec = 0;
+ /*
+ * XXX relies on clnt_tcp_create to bind
+ * to a reserved socket.
+ */
+ clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers,
+ mnttcp_ok ? nconf : getnetconfigent("udp"));
+ if (clp == NULL) {
if ((opflags & ISBGRND) == 0)
- warnx("%s", clnt_sperror(clp,
- "bad MNT RPC"));
+ clnt_pcreateerror("Cannot MNT RPC");
} else {
- retrycnt = 0;
+ CLNT_CONTROL(clp, CLSET_RETRY_TIMEOUT,
+ (char *)&pertry);
+ clp->cl_auth = authsys_create_default();
+ try.tv_sec = 10;
+ try.tv_usec = 0;
+ if (nfsargsp->flags & NFSMNT_KERB)
+ nfhret.auth = RPCAUTH_KERB4;
+ else
+ nfhret.auth = RPCAUTH_UNIX;
+ nfhret.vers = mntvers;
+ clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
+ xdr_dir, spec, xdr_fh, &nfhret, try);
+ if (clnt_stat != RPC_SUCCESS) {
+ if (clnt_stat == RPC_PROGVERSMISMATCH) {
+ if (mountmode == ANY) {
+ mountmode = V2;
+ goto tryagain;
+ } else {
+ errx(1, "%s",
+ clnt_sperror(clp, "MNT RPC"));
+ }
+ }
+ if ((opflags & ISBGRND) == 0)
+ warnx("%s", clnt_sperror(clp,
+ "bad MNT RPC"));
+ } else {
+ retrycnt = 0;
+ }
+ auth_destroy(clp->cl_auth);
+ clnt_destroy(clp);
+ so = RPC_ANYSOCK;
}
- auth_destroy(clp->cl_auth);
- clnt_destroy(clp);
- so = RPC_ANYSOCK;
}
- }
- if (--retrycnt > 0) {
- if (opflags & BGRND) {
- warnx("Cannot immediately mount %s:%s, "
- "backgrounding", hostp, spec);
- opflags &= ~BGRND;
- if ((i = fork())) {
- if (i == -1)
- err(1, "nqnfs 2");
- exit(0);
+ if (--retrycnt > 0) {
+ if (opflags & BGRND) {
+ warnx("Cannot immediately mount %s:%s, "
+ "backgrounding", hostp, spec);
+ opflags &= ~BGRND;
+ if ((i = fork())) {
+ if (i == -1)
+ err(1, "nqnfs 2");
+ exit(0);
+ }
+ (void) setsid();
+ (void) close(STDIN_FILENO);
+ (void) close(STDOUT_FILENO);
+ (void) close(STDERR_FILENO);
+ (void) chdir("/");
+ opflags |= ISBGRND;
}
- (void) setsid();
- (void) close(STDIN_FILENO);
- (void) close(STDOUT_FILENO);
- (void) close(STDERR_FILENO);
- (void) chdir("/");
- opflags |= ISBGRND;
+ sleep(60);
}
- sleep(60);
}
+ if (nfhret.stat == 0)
+ break;
+ ai = ai->ai_next;
}
+ freeaddrinfo(ai_nfs);
if (nfhret.stat) {
if (opflags & ISBGRND)
exit(1);
warnx("can't access %s: %s", spec, strerror(nfhret.stat));
return (0);
}
- saddr.sin_port = htons(tport);
{
- nfsargsp->addr = (struct sockaddr *) &saddr;
- nfsargsp->addrlen = sizeof (saddr);
+ nfsargsp->addr = (struct sockaddr *) nfs_nb.buf;
+ nfsargsp->addrlen = nfs_nb.len;
}
nfsargsp->fh = nfhret.nfh;
nfsargsp->fhsize = nfhret.fhsize;
diff --git a/sbin/mountd/mountd.c b/sbin/mountd/mountd.c
index 2f46a9f2ca9c..b5277656ac1e 100644
--- a/sbin/mountd/mountd.c
+++ b/sbin/mountd/mountd.c
@@ -50,12 +50,15 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpcsvc/mount.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
@@ -83,6 +86,10 @@ static const char rcsid[] =
#include <stdarg.h>
#endif
+#ifndef MOUNTDLOCK
+#define MOUNTDLOCK "/var/run/mountd.lock"
+#endif
+
/*
* Structures for keeping the mount list and export list
*/
@@ -117,13 +124,13 @@ struct exportlist {
#define EX_LINKED 0x1
struct netmsk {
- u_int32_t nt_net;
+ struct sockaddr_storage nt_net;
u_int32_t nt_mask;
char *nt_name;
};
union grouptypes {
- struct hostent *gt_hostent;
+ struct addrinfo *gt_addrinfo;
struct netmsk gt_net;
};
@@ -157,8 +164,8 @@ void add_dlist __P((struct dirlist **, struct dirlist *,
void add_mlist __P((char *, char *));
int check_dirpath __P((char *));
int check_options __P((struct dirlist *));
-int chk_host __P((struct dirlist *, u_int32_t, int *, int *));
-void del_mlist __P((char *, char *));
+int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *));
+int del_mlist __P((char *, char *, struct sockaddr *));
struct dirlist *dirp_search __P((struct dirlist *, char *));
int do_mount __P((struct exportlist *, struct grouplist *, int,
struct xucred *, char *, int, struct statfs *));
@@ -186,18 +193,25 @@ void nextfield __P((char **, char **));
void out_of_mem __P((void));
void parsecred __P((char *, struct xucred *));
int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *));
-int scan_tree __P((struct dirlist *, u_int32_t));
+int scan_tree __P((struct dirlist *, struct sockaddr *));
static void usage __P((void));
int xdr_dir __P((XDR *, char *));
int xdr_explist __P((XDR *, caddr_t));
int xdr_fhs __P((XDR *, caddr_t));
int xdr_mlist __P((XDR *, caddr_t));
+void terminate __P((int));
/* C library */
int getnetgrent();
void endnetgrent();
void setnetgrent();
+static int bitcmp __P((void *, void *, int));
+static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int));
+static int sacmp __P((struct sockaddr *, struct sockaddr *));
+static int allones __P((struct sockaddr_storage *, int));
+static int countones __P((struct sockaddr *));
+
struct exportlist *exphead;
struct mountlist *mlhead;
struct grouplist *grphead;
@@ -213,7 +227,16 @@ int force_v2 = 0;
int resvport_only = 1;
int dir_only = 1;
int log = 0;
+
int opt_flags;
+static int have_v6 = 1;
+#ifdef NI_WITHSCOPEID
+static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID;
+#else
+static const int ninumeric = NI_NUMERICHOST;
+#endif
+
+int mountdlockfd;
/* Bits for above */
#define OP_MAPROOT 0x01
#define OP_MAPALL 0x02
@@ -221,6 +244,7 @@ int opt_flags;
#define OP_MASK 0x08
#define OP_NET 0x10
#define OP_ALLDIRS 0x40
+#define OP_MASKLEN 0x200
#ifdef DEBUG
int debug = 1;
@@ -242,10 +266,26 @@ main(argc, argv)
int argc;
char **argv;
{
- SVCXPRT *udptransp, *tcptransp;
+ SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp;
+ struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf;
+ int udpsock, tcpsock, udp6sock, tcp6sock;
+ int xcreated = 0, s;
+ int one = 1;
int c, error, mib[3];
struct vfsconf vfc;
+ /* Check that another mountd isn't already running. */
+
+ if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1)
+ err(1, "%s", MOUNTDLOCK);
+
+ if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
+ errx(1, "another rpc.mountd is already running. Aborting");
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0)
+ have_v6 = 0;
+ else
+ close(s);
error = getvfsbyname("nfs", &vfc);
if (error && vfsisloadable("nfs")) {
if(vfsload("nfs"))
@@ -301,12 +341,38 @@ main(argc, argv)
signal(SIGQUIT, SIG_IGN);
}
signal(SIGHUP, (void (*) __P((int))) get_exportlist);
+ signal(SIGTERM, terminate);
{ FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");
if (pidfile != NULL) {
fprintf(pidfile, "%d\n", getpid());
fclose(pidfile);
}
}
+ rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL);
+ rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL);
+ udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ /*
+ * We're doing host-based access checks here, so don't allow
+ * v4-in-v6 to confuse things. The kernel will disable it
+ * by default on NFS sockets too.
+ */
+ if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &one, sizeof one) < 0){
+ syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket");
+ exit(1);
+ }
+ if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &one, sizeof one) < 0){
+ syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket");
+ exit(1);
+ }
+ udpconf = getnetconfigent("udp");
+ tcpconf = getnetconfigent("tcp");
+ udp6conf = getnetconfigent("udp6");
+ tcp6conf = getnetconfigent("tcp6");
if (!resvport_only) {
mib[0] = CTL_VFS;
mib[1] = vfc.vfc_typenum;
@@ -322,17 +388,90 @@ main(argc, argv)
syslog(LOG_ERR, "can't create socket");
exit(1);
}
- pmap_unset(RPCPROG_MNT, 1);
- pmap_unset(RPCPROG_MNT, 3);
- if (!force_v2)
- if (!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
- !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
- syslog(LOG_ERR, "can't register mount");
- exit(1);
- }
- if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
- !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP)) {
- syslog(LOG_ERR, "can't register mount");
+ if (udpsock != -1 && udpconf != NULL) {
+ bindresvport(udpsock, NULL);
+ udptransp = svc_dg_create(udpsock, 0, 0);
+ if (udptransp != NULL) {
+ if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, udpconf))
+ syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, udpconf))
+ syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create UDP services");
+
+ }
+ if (tcpsock != -1 && tcpconf != NULL) {
+ bindresvport(tcpsock, NULL);
+ listen(tcpsock, SOMAXCONN);
+ tcptransp = svc_vc_create(tcpsock, 0, 0);
+ if (tcptransp != NULL) {
+ if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, tcpconf))
+ syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, tcpconf))
+ syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create TCP service");
+
+ }
+ if (udp6sock != -1 && udp6conf != NULL) {
+ bindresvport(udp6sock, NULL);
+ udp6transp = svc_dg_create(udp6sock, 0, 0);
+ if (udp6transp != NULL) {
+ if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, udp6conf))
+ syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, udp6conf))
+ syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create UDP6 service");
+
+ }
+ if (tcp6sock != -1 && tcp6conf != NULL) {
+ bindresvport(tcp6sock, NULL);
+ listen(tcp6sock, SOMAXCONN);
+ tcp6transp = svc_vc_create(tcp6sock, 0, 0);
+ if (tcp6transp != NULL) {
+ if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, tcp6conf))
+ syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, tcp6conf))
+ syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create TCP6 service");
+
+ }
+ if (xcreated == 0) {
+ syslog(LOG_ERR, "could not create any services");
exit(1);
}
svc_run();
@@ -361,20 +500,38 @@ mntsrv(rqstp, transp)
struct fhreturn fhr;
struct stat stb;
struct statfs fsb;
- struct hostent *hp;
- struct in_addr saddrin;
- u_int32_t saddr;
+ struct addrinfo *ai;
+ char host[NI_MAXHOST], numerichost[NI_MAXHOST];
+ int lookup_failed = 1;
+ struct sockaddr *saddr;
u_short sport;
char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN];
int bad = 0, defset, hostset;
sigset_t sighup_mask;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
- saddr = transp->xp_raddr.sin_addr.s_addr;
- saddrin = transp->xp_raddr.sin_addr;
- sport = ntohs(transp->xp_raddr.sin_port);
- hp = (struct hostent *)NULL;
+ saddr = svc_getrpccaller(transp)->buf;
+ switch (saddr->sa_family) {
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)saddr;
+ sport = ntohs(sin6->sin6_port);
+ break;
+ case AF_INET:
+ sin = (struct sockaddr_in *)saddr;
+ sport = ntohs(sin->sin_port);
+ break;
+ default:
+ syslog(LOG_ERR, "request from unknown address family");
+ return;
+ }
+ lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host,
+ NULL, 0, 0);
+ getnameinfo(saddr, saddr->sa_len, numerichost,
+ sizeof numerichost, NULL, 0, NI_NUMERICHOST);
+ ai = NULL;
switch (rqstp->rq_proc) {
case NULLPROC:
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
@@ -384,13 +541,13 @@ mntsrv(rqstp, transp)
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"mount request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_getargs(transp, xdr_dir, rpcpath)) {
syslog(LOG_NOTICE, "undecodable mount request from %s",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_decode(transp);
return;
}
@@ -403,12 +560,12 @@ mntsrv(rqstp, transp)
if (realpath(rpcpath, dirpath) == NULL ||
stat(dirpath, &stb) < 0 ||
(!S_ISDIR(stb.st_mode) &&
- (dir_only || !S_ISREG(stb.st_mode))) ||
+ (dir_only || !S_ISREG(stb.st_mode))) ||
statfs(dirpath, &fsb) < 0) {
chdir("/"); /* Just in case realpath doesn't */
syslog(LOG_NOTICE,
"mount request from %s for non existent path %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
if (debug)
warnx("stat failed on %s", dirpath);
bad = ENOENT; /* We will send error reply later */
@@ -420,9 +577,9 @@ mntsrv(rqstp, transp)
hostset = defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
- chk_host(dp, saddr, &defset, &hostset)) ||
- (defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
- scan_tree(ep->ex_dirl, saddr) == 0))) {
+ chk_host(dp, saddr, &defset, &hostset)) ||
+ (defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
+ scan_tree(ep->ex_dirl, saddr) == 0))) {
if (bad) {
if (!svc_sendreply(transp, xdr_long,
(caddr_t)&bad))
@@ -448,25 +605,21 @@ mntsrv(rqstp, transp)
}
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
syslog(LOG_ERR, "can't send reply");
- if (hp == NULL)
- hp = gethostbyaddr((caddr_t)&saddr,
- sizeof(saddr), AF_INET);
- if (hp)
- add_mlist(hp->h_name, dirpath);
+ if (!lookup_failed)
+ add_mlist(host, dirpath);
else
- add_mlist(inet_ntoa(saddrin),
- dirpath);
+ add_mlist(numerichost, dirpath);
if (debug)
warnx("mount successful");
if (log)
syslog(LOG_NOTICE,
"mount request succeeded from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
} else {
bad = EACCES;
syslog(LOG_NOTICE,
"mount request denied from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
}
if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad))
@@ -479,56 +632,54 @@ mntsrv(rqstp, transp)
else if (log)
syslog(LOG_NOTICE,
"dump request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
case RPCMNT_UMOUNT:
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"umount request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_getargs(transp, xdr_dir, rpcpath)) {
syslog(LOG_NOTICE, "undecodable umount request from %s",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_decode(transp);
return;
}
if (realpath(rpcpath, dirpath) == NULL) {
syslog(LOG_NOTICE, "umount request from %s "
"for non existent path %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
}
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
syslog(LOG_ERR, "can't send reply");
- hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
- if (hp)
- del_mlist(hp->h_name, dirpath);
- del_mlist(inet_ntoa(saddrin), dirpath);
+ if (!lookup_failed)
+ del_mlist(host, dirpath, saddr);
+ del_mlist(numerichost, dirpath, saddr);
if (log)
syslog(LOG_NOTICE,
"umount request succeeded from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
return;
case RPCMNT_UMNTALL:
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"umountall request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
syslog(LOG_ERR, "can't send reply");
- hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
- if (hp)
- del_mlist(hp->h_name, (char *)NULL);
- del_mlist(inet_ntoa(saddrin), (char *)NULL);
+ if (!lookup_failed)
+ del_mlist(host, NULL, saddr);
+ del_mlist(numerichost, NULL, saddr);
if (log)
syslog(LOG_NOTICE,
"umountall request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
case RPCMNT_EXPORT:
if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL))
@@ -536,7 +687,7 @@ mntsrv(rqstp, transp)
if (log)
syslog(LOG_NOTICE,
"export request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
default:
svcerr_noproc(transp);
@@ -690,7 +841,7 @@ put_exlist(dp, xdrsp, adp, putdefp)
if (grp->gr_type == GT_HOST) {
if (!xdr_bool(xdrsp, &true))
return (1);
- strp = grp->gr_ptr.gt_hostent->h_name;
+ strp = grp->gr_ptr.gt_addrinfo->ai_canonname;
if (!xdr_string(xdrsp, &strp,
RPCMNT_NAMELEN))
return (1);
@@ -732,7 +883,7 @@ get_exportlist()
struct exportlist **epp;
struct dirlist *dirhead;
struct statfs fsb, *fsp;
- struct hostent *hpe;
+ struct addrinfo *ai;
struct xucred anon;
char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;
int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp;
@@ -786,7 +937,7 @@ get_exportlist()
fsp->f_flags | MNT_UPDATE,
(caddr_t)&targs) < 0)
syslog(LOG_ERR, "can't delete exports for %s",
- fsp->f_mntonname);
+ fsp->f_mntonname);
}
fsp++;
}
@@ -874,9 +1025,9 @@ get_exportlist()
else
out_of_mem();
if (debug)
- warnx("making new ep fs=0x%x,0x%x",
- fsb.f_fsid.val[0],
- fsb.f_fsid.val[1]);
+ warnx("making new ep fs=0x%x,0x%x",
+ fsb.f_fsid.val[0],
+ fsb.f_fsid.val[1]);
} else if (debug)
warnx("found ep fs=0x%x,0x%x",
fsb.f_fsid.val[0],
@@ -944,14 +1095,17 @@ get_exportlist()
if (debug)
warnx("adding a default entry");
/* add a default group and make the grp list NULL */
- hpe = (struct hostent *)malloc(sizeof(struct hostent));
- if (hpe == (struct hostent *)NULL)
- out_of_mem();
- hpe->h_name = strdup("Default");
- hpe->h_addrtype = AF_INET;
- hpe->h_length = sizeof (u_int32_t);
- hpe->h_addr_list = (char **)NULL;
- grp->gr_ptr.gt_hostent = hpe;
+ ai = malloc(sizeof(struct addrinfo));
+ ai->ai_flags = 0;
+ ai->ai_family = AF_INET; /* XXXX */
+ ai->ai_socktype = SOCK_DGRAM;
+ /* setting the length to 0 will match anything */
+ ai->ai_addrlen = 0;
+ ai->ai_flags = AI_CANONNAME;
+ ai->ai_canonname = strdup("Default");
+ ai->ai_addr = NULL;
+ ai->ai_next = NULL;
+ grp->gr_ptr.gt_addrinfo = ai;
/*
* Don't allow a network export coincide with a list of
@@ -961,13 +1115,13 @@ get_exportlist()
getexp_err(ep, tgrp);
goto nextline;
- /*
- * If an export list was specified on this line, make sure
+ /*
+ * If an export list was specified on this line, make sure
* that we have at least one valid entry, otherwise skip it.
*/
} else {
grp = tgrp;
- while (grp && grp->gr_type == GT_IGNORE)
+ while (grp && grp->gr_type == GT_IGNORE)
grp = grp->gr_next;
if (! grp) {
getexp_err(ep, tgrp);
@@ -1219,19 +1373,27 @@ add_dlist(dpp, newdp, grp, flags)
/*
* Search for a dirpath on the export point.
*/
+void *
+test()
+{
+}
+
+/*
+ * Search for a dirpath on the export point.
+ */
struct dirlist *
-dirp_search(dp, dirpath)
+dirp_search(dp, dirp)
struct dirlist *dp;
- char *dirpath;
+ char *dirp;
{
int cmp;
if (dp) {
- cmp = strcmp(dp->dp_dirp, dirpath);
+ cmp = strcmp(dp->dp_dirp, dirp);
if (cmp > 0)
- return (dirp_search(dp->dp_left, dirpath));
+ return (dirp_search(dp->dp_left, dirp));
else if (cmp < 0)
- return (dirp_search(dp->dp_right, dirpath));
+ return (dirp_search(dp->dp_right, dirp));
else
return (dp);
}
@@ -1239,18 +1401,59 @@ dirp_search(dp, dirpath)
}
/*
+ * Some helper functions for netmasks. They all assume masks in network
+ * order (big endian).
+ */
+static int
+bitcmp(void *dst, void *src, int bitlen)
+{
+ int i;
+ u_int8_t *p1 = dst, *p2 = src;
+ u_int8_t bitmask;
+ int bytelen, bitsleft;
+
+ bytelen = bitlen / 8;
+ bitsleft = bitlen % 8;
+
+ if (debug) {
+ printf("comparing:\n");
+ for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++)
+ printf("%02x", p1[i]);
+ printf("\n");
+ for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++)
+ printf("%02x", p2[i]);
+ printf("\n");
+ }
+
+ for (i = 0; i < bytelen; i++) {
+ if (*p1 != *p2)
+ return 1;
+ p1++;
+ p2++;
+ }
+
+ for (i = 0; i < bitsleft; i++) {
+ bitmask = 1 << (7 - i);
+ if ((*p1 & bitmask) != (*p2 & bitmask))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* Scan for a host match in a directory tree.
*/
int
chk_host(dp, saddr, defsetp, hostsetp)
struct dirlist *dp;
- u_int32_t saddr;
+ struct sockaddr *saddr;
int *defsetp;
int *hostsetp;
{
struct hostlist *hp;
struct grouplist *grp;
- u_int32_t **addrp;
+ struct addrinfo *ai;
if (dp) {
if (dp->dp_flag & DP_DEFSET)
@@ -1260,22 +1463,22 @@ chk_host(dp, saddr, defsetp, hostsetp)
grp = hp->ht_grp;
switch (grp->gr_type) {
case GT_HOST:
- addrp = (u_int32_t **)
- grp->gr_ptr.gt_hostent->h_addr_list;
- while (*addrp) {
- if (**addrp == saddr) {
- *hostsetp = (hp->ht_flag | DP_HOSTSET);
- return (1);
+ ai = grp->gr_ptr.gt_addrinfo;
+ for (; ai; ai = ai->ai_next) {
+ if (!sacmp(ai->ai_addr, saddr)) {
+ *hostsetp =
+ (hp->ht_flag | DP_HOSTSET);
+ return (1);
+ }
}
- addrp++;
- }
break;
case GT_NET:
- if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
- grp->gr_ptr.gt_net.nt_net) {
- *hostsetp = (hp->ht_flag | DP_HOSTSET);
- return (1);
- }
+ if (!netpartcmp(saddr,
+ (struct sockaddr *) &grp->gr_ptr.gt_net.nt_net,
+ grp->gr_ptr.gt_net.nt_mask)) {
+ *hostsetp = (hp->ht_flag | DP_HOSTSET);
+ return (1);
+ }
break;
};
hp = hp->ht_next;
@@ -1290,7 +1493,7 @@ chk_host(dp, saddr, defsetp, hostsetp)
int
scan_tree(dp, saddr)
struct dirlist *dp;
- u_int32_t saddr;
+ struct sockaddr *saddr;
{
int defset, hostset;
@@ -1392,6 +1595,11 @@ do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr)
opt_flags |= OP_MASK;
} else if (cpoptarg && (!strcmp(cpopt, "network") ||
!strcmp(cpopt, "n"))) {
+ if (strchr(cpoptarg, '/') != NULL) {
+ if (debug)
+ fprintf(stderr, "setting OP_MASKLEN\n");
+ opt_flags |= OP_MASKLEN;
+ }
if (grp->gr_type != GT_NULL) {
syslog(LOG_ERR, "network/host conflict");
return (1);
@@ -1442,84 +1650,40 @@ get_host(cp, grp, tgrp)
struct grouplist *tgrp;
{
struct grouplist *checkgrp;
- struct hostent *hp, *nhp;
- char **addrp, **naddrp;
- struct hostent t_host;
+ struct addrinfo *ai, hints;
+ int ecode;
+ char host[NI_MAXHOST];
int i;
- u_int32_t saddr;
char *aptr[2];
- if (grp->gr_type != GT_NULL)
+ if (grp->gr_type != GT_NULL) {
+ syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp);
return (1);
- if ((hp = gethostbyname(cp)) == NULL) {
- if (isdigit(*cp)) {
- saddr = inet_addr(cp);
- if (saddr == -1) {
- syslog(LOG_ERR, "inet_addr failed for %s", cp);
- return (1);
- }
- if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
- AF_INET)) == NULL) {
- hp = &t_host;
- hp->h_name = cp;
- hp->h_addrtype = AF_INET;
- hp->h_length = sizeof (u_int32_t);
- hp->h_addr_list = aptr;
- aptr[0] = (char *)&saddr;
- aptr[1] = (char *)NULL;
- }
- } else {
- syslog(LOG_ERR, "gethostbyname failed for %s", cp);
- return (1);
- }
}
- /*
- * Sanity check: make sure we don't already have an entry
- * for this host in the grouplist.
- */
- checkgrp = tgrp;
- while (checkgrp != NULL) {
- if (checkgrp->gr_type == GT_HOST &&
- checkgrp->gr_ptr.gt_hostent != NULL &&
- (!strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name)
- || *(u_int32_t *)checkgrp->gr_ptr.gt_hostent->h_addr ==
- *(u_int32_t *)hp->h_addr)) {
- grp->gr_type = GT_IGNORE;
- return(0);
- }
- checkgrp = checkgrp->gr_next;
- }
-
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(cp, NULL, &hints, &ai);
+ if (ecode != 0) {
+ syslog(LOG_ERR,"can't get address info for "
+ "host %s", cp);
+ return 1;
+ }
grp->gr_type = GT_HOST;
- nhp = grp->gr_ptr.gt_hostent = (struct hostent *)
- malloc(sizeof(struct hostent));
- if (nhp == (struct hostent *)NULL)
- out_of_mem();
- memmove(nhp, hp, sizeof(struct hostent));
- i = strlen(hp->h_name)+1;
- nhp->h_name = (char *)malloc(i);
- if (nhp->h_name == (char *)NULL)
- out_of_mem();
- memmove(nhp->h_name, hp->h_name, i);
- addrp = hp->h_addr_list;
- i = 1;
- while (*addrp++)
- i++;
- naddrp = nhp->h_addr_list = (char **)malloc(i*sizeof(char *));
- if (naddrp == (char **)NULL)
- out_of_mem();
- addrp = hp->h_addr_list;
- while (*addrp) {
- *naddrp = (char *)malloc(hp->h_length);
- if (*naddrp == (char *)NULL)
- out_of_mem();
- memmove(*naddrp, *addrp, hp->h_length);
- addrp++;
- naddrp++;
- }
- *naddrp = (char *)NULL;
- if (debug)
- warnx("got host %s", hp->h_name);
+ grp->gr_ptr.gt_addrinfo = ai;
+ while (ai != NULL) {
+ if (ai->ai_canonname == NULL) {
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host,
+ sizeof host, NULL, 0, ninumeric) != 0)
+ strlcpy(host, "?", sizeof(host));
+ ai->ai_canonname = strdup(host);
+ ai->ai_flags |= AI_CANONNAME;
+ } else
+ ai->ai_flags &= ~AI_CANONNAME;
+ if (debug)
+ (void)fprintf(stderr, "got host %s\n", ai->ai_canonname);
+ ai = ai->ai_next;
+ }
return (0);
}
@@ -1597,68 +1761,64 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
int dirplen;
struct statfs *fsb;
{
- char *cp = (char *)NULL;
- u_int32_t **addrp;
+ struct sockaddr *addrp;
+ struct sockaddr_storage ss;
+ struct addrinfo *ai;
+ int addrlen;
+ char *cp = NULL;
int done;
char savedc = '\0';
- struct sockaddr_in sin, imask;
union {
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
+ struct adosfs_args aa;
#endif
struct ntfs_args na;
} args;
- u_int32_t net;
args.ua.fspec = 0;
args.ua.export.ex_flags = exflags;
args.ua.export.ex_anon = *anoncrp;
args.ua.export.ex_indexfile = ep->ex_indexfile;
- memset(&sin, 0, sizeof(sin));
- memset(&imask, 0, sizeof(imask));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- imask.sin_family = AF_INET;
- imask.sin_len = sizeof(sin);
- if (grp->gr_type == GT_HOST)
- addrp = (u_int32_t **)grp->gr_ptr.gt_hostent->h_addr_list;
- else
- addrp = (u_int32_t **)NULL;
+ if (grp->gr_type == GT_HOST) {
+ ai = grp->gr_ptr.gt_addrinfo;
+ addrp = ai->ai_addr;
+ addrlen = ai->ai_addrlen;
+ } else
+ addrp = NULL;
done = FALSE;
while (!done) {
switch (grp->gr_type) {
case GT_HOST:
- if (addrp) {
- sin.sin_addr.s_addr = **addrp;
- args.ua.export.ex_addrlen = sizeof(sin);
- } else
- args.ua.export.ex_addrlen = 0;
- args.ua.export.ex_addr = (struct sockaddr *)&sin;
+ if (addrp != NULL && addrp->sa_family == AF_INET6 &&
+ have_v6 == 0)
+ goto skip;
+ args.ua.export.ex_addr = addrp;
+ args.ua.export.ex_addrlen = addrlen;
args.ua.export.ex_masklen = 0;
break;
case GT_NET:
- if (grp->gr_ptr.gt_net.nt_mask)
- imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask;
- else {
- net = ntohl(grp->gr_ptr.gt_net.nt_net);
- if (IN_CLASSA(net))
- imask.sin_addr.s_addr = inet_addr("255.0.0.0");
- else if (IN_CLASSB(net))
- imask.sin_addr.s_addr =
- inet_addr("255.255.0.0");
- else
- imask.sin_addr.s_addr =
- inet_addr("255.255.255.0");
- grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr;
+ args.ua.export.ex_addr = (struct sockaddr *)
+ &grp->gr_ptr.gt_net.nt_net;
+ if (args.ua.export.ex_addr->sa_family == AF_INET6 &&
+ have_v6 == 0)
+ goto skip;
+ args.ua.export.ex_addrlen =
+ args.ua.export.ex_addr->sa_len;
+ memset(&ss, 0, sizeof ss);
+ ss.ss_family = args.ua.export.ex_addr->sa_family;
+ ss.ss_len = args.ua.export.ex_addr->sa_len;
+ if (allones(&ss, grp->gr_ptr.gt_net.nt_mask) != 0) {
+ syslog(LOG_ERR, "Bad network flag");
+ if (cp)
+ *cp = savedc;
+ return (1);
}
- sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net;
- args.ua.export.ex_addr = (struct sockaddr *)&sin;
- args.ua.export.ex_addrlen = sizeof (sin);
- args.ua.export.ex_mask = (struct sockaddr *)&imask;
- args.ua.export.ex_masklen = sizeof (imask);
+ args.ua.export.ex_mask = (struct sockaddr *)&ss;
+ args.ua.export.ex_masklen = ss.ss_len;
break;
case GT_IGNORE:
return(0);
@@ -1678,7 +1838,7 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
* exportable file systems and not just "ufs".
*/
while (mount(fsb->f_fstypename, dirp,
- fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
+ fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
if (cp)
*cp-- = savedc;
else
@@ -1707,10 +1867,15 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
savedc = *cp;
*cp = '\0';
}
+skip:
if (addrp) {
- ++addrp;
- if (*addrp == (u_int32_t *)NULL)
+ ai = ai->ai_next;
+ if (ai == NULL)
done = TRUE;
+ else {
+ addrp = ai->ai_addr;
+ addrlen = ai->ai_addrlen;
+ }
} else
done = TRUE;
}
@@ -1729,47 +1894,105 @@ get_net(cp, net, maskflg)
int maskflg;
{
struct netent *np;
- long netaddr;
- struct in_addr inetaddr, inetaddr2;
- char *name;
+ char *name, *p, *prefp;
+ struct sockaddr_in sin, *sinp;
+ struct sockaddr *sa;
+ struct addrinfo hints, *ai = NULL;
+ char netname[NI_MAXHOST];
+ long preflen;
+ int ecode;
+
+ if ((opt_flags & OP_MASKLEN) && !maskflg) {
+ p = strchr(cp, '/');
+ *p = '\0';
+ prefp = p + 1;
+ }
- if (isdigit(*cp) && ((netaddr = inet_network(cp)) != -1)) {
- inetaddr = inet_makeaddr(netaddr, 0);
- /*
- * Due to arbitrary subnet masks, you don't know how many
- * bits to shift the address to make it into a network,
- * however you do know how to make a network address into
- * a host with host == 0 and then compare them.
- * (What a pest)
- */
- if (!maskflg) {
- setnetent(0);
- while ((np = getnetent())) {
- inetaddr2 = inet_makeaddr(np->n_net, 0);
- if (inetaddr2.s_addr == inetaddr.s_addr)
- break;
- }
- endnetent();
- }
- } else if ((np = getnetbyname(cp)) != NULL) {
- inetaddr = inet_makeaddr(np->n_net, 0);
+ if ((np = getnetbyname(cp)) != NULL) {
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof sin;
+ sin.sin_addr = inet_makeaddr(np->n_net, 0);
+ sa = (struct sockaddr *)&sin;
+ } else if (isdigit(*cp)) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(cp, NULL, &hints, &ai) != 0) {
+ /*
+ * If getaddrinfo() failed, try the inet4 network
+ * notation with less than 3 dots.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof sin;
+ sin.sin_addr = inet_makeaddr(inet_network(cp),0);
+ if (debug)
+ fprintf(stderr, "get_net: v4 addr %x\n",
+ sin.sin_addr.s_addr);
+ sa = (struct sockaddr *)&sin;
+ } else
+ sa = ai->ai_addr;
+ } else if (isxdigit(*cp) || *cp == ':') {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(cp, NULL, &hints, &ai) == 0)
+ sa = ai->ai_addr;
+ else
+ goto fail;
} else
- return (1);
+ goto fail;
+
+ ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname,
+ NULL, 0, ninumeric);
+ if (ecode != 0)
+ goto fail;
if (maskflg)
- net->nt_mask = inetaddr.s_addr;
+ net->nt_mask = countones(sa);
else {
+ if (opt_flags & OP_MASKLEN) {
+ preflen = strtol(prefp, NULL, 10);
+ if (preflen == LONG_MIN && errno == ERANGE)
+ goto fail;
+ net->nt_mask = (int)preflen;
+ *p = '/';
+ }
+
if (np)
name = np->n_name;
+ else {
+ if (getnameinfo(sa, sa->sa_len, netname, sizeof netname,
+ NULL, 0, ninumeric) != 0)
+ strlcpy(netname, "?", sizeof(netname));
+ name = netname;
+ }
+ net->nt_name = strdup(name);
+ memcpy(&net->nt_net, sa, sa->sa_len);
+ }
+
+ if (!maskflg && sa->sa_family == AF_INET &&
+ !(opt_flags & (OP_MASK|OP_MASKLEN))) {
+ sinp = (struct sockaddr_in *)sa;
+ if (IN_CLASSA(sinp->sin_addr.s_addr))
+ net->nt_mask = 8;
+ else if (IN_CLASSB(sinp->sin_addr.s_addr))
+ net->nt_mask = 16;
+ else if (IN_CLASSC(sinp->sin_addr.s_addr))
+ net->nt_mask = 24;
+ else if (IN_CLASSD(sinp->sin_addr.s_addr))
+ net->nt_mask = 28;
else
- name = inet_ntoa(inetaddr);
- net->nt_name = (char *)malloc(strlen(name) + 1);
- if (net->nt_name == (char *)NULL)
- out_of_mem();
- strcpy(net->nt_name, name);
- net->nt_net = inetaddr.s_addr;
+ net->nt_mask = 32; /* XXX */
}
- return (0);
+
+ if (ai)
+ freeaddrinfo(ai);
+ return 0;
+
+fail:
+ if (ai)
+ freeaddrinfo(ai);
+ return 1;
}
/*
@@ -1958,15 +2181,28 @@ get_mountlist()
fclose(mlfile);
}
-void
-del_mlist(hostp, dirp)
+int
+del_mlist(hostp, dirp, saddr)
char *hostp, *dirp;
+ struct sockaddr *saddr;
{
struct mountlist *mlp, **mlpp;
struct mountlist *mlp2;
+ u_short sport;
FILE *mlfile;
int fnd = 0;
-
+ char host[NI_MAXHOST];
+
+ switch (saddr->sa_family) {
+ case AF_INET6:
+ sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port);
+ break;
+ case AF_INET:
+ sport = ntohs(((struct sockaddr_in *)saddr)->sin_port);
+ break;
+ default:
+ return -1;
+ }
mlpp = &mlhead;
mlp = mlhead;
while (mlp) {
@@ -2034,17 +2270,11 @@ void
free_grp(grp)
struct grouplist *grp;
{
- char **addrp;
+ struct addrinfo *ai;
if (grp->gr_type == GT_HOST) {
- if (grp->gr_ptr.gt_hostent->h_name) {
- addrp = grp->gr_ptr.gt_hostent->h_addr_list;
- while (addrp && *addrp)
- free(*addrp++);
- free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list);
- free(grp->gr_ptr.gt_hostent->h_name);
- }
- free((caddr_t)grp->gr_ptr.gt_hostent);
+ if (grp->gr_ptr.gt_addrinfo != NULL)
+ freeaddrinfo(grp->gr_ptr.gt_addrinfo);
} else if (grp->gr_type == GT_NET) {
if (grp->gr_ptr.gt_net.nt_name)
free(grp->gr_ptr.gt_net.nt_name);
@@ -2093,7 +2323,6 @@ check_options(dp)
/*
* Check an absolute directory path for any symbolic links. Return true
- * if no symbolic links are found.
*/
int
check_dirpath(dirp)
@@ -2134,3 +2363,146 @@ get_num(cp)
}
return (res);
}
+
+static int
+netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen)
+{
+ void *src, *dst;
+
+ if (s1->sa_family != s2->sa_family)
+ return 1;
+
+ switch (s1->sa_family) {
+ case AF_INET:
+ src = &((struct sockaddr_in *)s1)->sin_addr;
+ dst = &((struct sockaddr_in *)s2)->sin_addr;
+ if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8)
+ return 1;
+ break;
+ case AF_INET6:
+ src = &((struct sockaddr_in6 *)s1)->sin6_addr;
+ dst = &((struct sockaddr_in6 *)s2)->sin6_addr;
+ if (((struct sockaddr_in6 *)s1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)s2)->sin6_scope_id)
+ return 1;
+ if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8)
+ return 1;
+ break;
+ default:
+ return 1;
+ }
+
+ return bitcmp(src, dst, bitlen);
+}
+
+static int
+allones(struct sockaddr_storage *ssp, int bitlen)
+{
+ u_int8_t *p;
+ int bytelen, bitsleft, i;
+ int zerolen;
+
+ switch (ssp->ss_family) {
+ case AF_INET:
+ p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr;
+ zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr);
+ break;
+ case AF_INET6:
+ p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr;
+ zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr);
+ break;
+ default:
+ return -1;
+ }
+
+ memset(p, 0, zerolen);
+
+ bytelen = bitlen / 8;
+ bitsleft = bitlen % 8;
+
+ if (bytelen > zerolen)
+ return -1;
+
+ for (i = 0; i < bytelen; i++)
+ *p++ = 0xff;
+
+ for (i = 0; i < bitsleft; i++)
+ *p |= 1 << (7 - i);
+
+ return 0;
+}
+
+static int
+countones(struct sockaddr *sa)
+{
+ void *mask;
+ int i, bits = 0, bytelen;
+ u_int8_t *p;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr;
+ bytelen = 4;
+ break;
+ case AF_INET6:
+ mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr;
+ bytelen = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ p = mask;
+
+ for (i = 0; i < bytelen; i++, p++) {
+ if (*p != 0xff) {
+ for (bits = 0; bits < 8; bits++) {
+ if (!(*p & (1 << (7 - bits))))
+ break;
+ }
+ break;
+ }
+ }
+
+ return (i * 8 + bits);
+}
+
+static int
+sacmp(struct sockaddr *sa1, struct sockaddr *sa2)
+{
+ void *p1, *p2;
+ int len;
+
+ if (sa1->sa_family != sa2->sa_family)
+ return 1;
+
+ switch (sa1->sa_family) {
+ case AF_INET:
+ p1 = &((struct sockaddr_in *)sa1)->sin_addr;
+ p2 = &((struct sockaddr_in *)sa2)->sin_addr;
+ len = 4;
+ break;
+ case AF_INET6:
+ p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
+ p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
+ len = 16;
+ if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
+ return 1;
+ break;
+ default:
+ return 1;
+ }
+
+ return memcmp(p1, p2, len);
+}
+
+void terminate(sig)
+int sig;
+{
+ close(mountdlockfd);
+ unlink(MOUNTDLOCK);
+ pmap_unset(RPCPROG_MNT, 1);
+ pmap_unset(RPCPROG_MNT, 3);
+ exit (0);
+}
diff --git a/sbin/nfsd/nfsd.8 b/sbin/nfsd/nfsd.8
index fb44149bb4d8..0031ea1b926e 100644
--- a/sbin/nfsd/nfsd.8
+++ b/sbin/nfsd/nfsd.8
@@ -42,7 +42,7 @@
server
.Sh SYNOPSIS
.Nm
-.Op Fl arut
+.Op Fl ardut
.Op Fl n Ar num_servers
.Op Fl h Ar bindip
.Sh DESCRIPTION
@@ -64,13 +64,19 @@ The following options are available:
Register the
.Tn NFS
service with
-.Xr portmap 8
+.Xr rpcbind 8
without creating any servers.
This option can be used along with the
.Fl u
or
.Fl t
-options to re-register NFS if the portmap server is restarted.
+options to re-register NFS if the rpcbind server is restarted.
+.It Fl d
+Unregister the
+.Tn NFS
+service with
+.Xr rpcbind 8
+without creating any servers.
.It Fl n
Specifies how many servers to create.
.It Fl h Ar bindip
@@ -147,6 +153,16 @@ that the NFS sockets can only be accessed by the inside interface.
would then be used to block nfs-related packets that come in on the outside
interface.
.Pp
+.Nm
+has to be terminated with SIGUSR1 and cannot be killed with SIGTERM oder SIGQUIT.
+.Nm
+needs to ignore these signals in order to stay alive as long
+as possible during a shutdown, otherwise loopback mounts will
+not be able to unmount. If you have to kill
+.Nm
+just do a
+.Dq Li "kill -USR1 <PID of master nfsd>"
+.Pp
The
.Nm
utility exits 0 on success, and >0 if an error occurs.
@@ -156,7 +172,7 @@ utility exits 0 on success, and >0 if an error occurs.
.Xr kldload 8 ,
.Xr mountd 8 ,
.Xr nfsiod 8 ,
-.Xr portmap 8 ,
+.Xr rpcbind 8 ,
.Xr ipfw 8
.Sh HISTORY
The
diff --git a/sbin/nfsd/nfsd.c b/sbin/nfsd/nfsd.c
index 2d923a42652b..959f0fb04d18 100644
--- a/sbin/nfsd/nfsd.c
+++ b/sbin/nfsd/nfsd.c
@@ -58,9 +58,6 @@ static const char rcsid[] =
#include <netdb.h>
#include <arpa/inet.h>
-#ifdef ISO
-#include <netiso/iso.h>
-#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
@@ -76,6 +73,7 @@ static const char rcsid[] =
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
+#include <netdb.h>
/* Global defs */
#ifdef DEBUG
@@ -103,15 +101,23 @@ struct timeval ktv;
NFSKERBKEYSCHED_T kerb_keysched;
#endif
-void nonfs __P((int));
-void reapchild __P((int));
-void setbindhost __P((struct sockaddr_in *ia, const char *bindhost));
+#define MAXNFSDCNT 20
+#define DEFNFSDCNT 4
+pid_t children[MAXNFSDCNT]; /* PIDs of children */
+int nfsdcnt; /* number of children */
+
+void cleanup(int);
+void killchildren(void);
+void nonfs (int);
+void reapchild (int);
+int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints);
#ifdef OLD_SETPROCTITLE
#ifdef __FreeBSD__
-void setproctitle __P((char *));
+void setproctitle (char *);
#endif
#endif
-void usage __P((void));
+void unregistration (void);
+void usage (void);
/*
* Nfs server daemon mostly just a user context for nfssvc()
@@ -119,7 +125,7 @@ void usage __P((void));
* 1 - do file descriptor and signal cleanup
* 2 - fork the nfsd(s)
* 3 - create server socket(s)
- * 4 - register socket with portmap
+ * 4 - register socket with rpcbind
*
* For connectionless protocols, just pass the socket into the kernel via.
* nfssvc().
@@ -127,7 +133,8 @@ void usage __P((void));
* socket from accept, pass the msgsock into the kernel via. nfssvc().
* The arguments are:
* -c - support iso cltp clients
- * -r - reregister with portmapper
+ * -r - reregister with rpcbind
+ * -d - unregister with rpcbind
* -t - support tcp nfs clients
* -u - support udp nfs clients
* followed by "n" which is the number of nfsds' to fork off
@@ -138,20 +145,20 @@ main(argc, argv, envp)
char *argv[], *envp[];
{
struct nfsd_args nfsdargs;
- struct sockaddr_in inetaddr, inetpeer;
-#ifdef ISO
- struct sockaddr_iso isoaddr, isopeer;
- char *cp;
-#endif
+ struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
+ struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
+ struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
+ struct sockaddr_in inetpeer;
+ struct sockaddr_in6 inet6peer;
fd_set ready, sockbits;
+ fd_set v4bits, v6bits;
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
- int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
- int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
- int bindhostc = 0, bindanyflag;
+ int nfssvc_flag, on = 1, unregister, reregister, sock;
+ int tcp6sock, ip6flag, tcpflag, tcpsock;
+ int udpflag, ecode, s;
+ int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt;
char **bindhost = NULL;
-#ifdef notyet
- int tp4sock, tpipsock;
-#endif
+ pid_t pid;
#ifdef NFSKERB
struct group *grp;
struct passwd *pwd;
@@ -184,18 +191,11 @@ main(argc, argv, envp)
LastArg = envp[-1] + strlen(envp[-1]);
#endif
-#define MAXNFSDCNT 20
-#define DEFNFSDCNT 4
nfsdcnt = DEFNFSDCNT;
- cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
- bindanyflag = tpipflag = udpflag = 0;
-#ifdef ISO
-#define GETOPT "ach:n:rtu"
-#define USAGE "[-acrtu] [-n num_servers] [-h bindip]"
-#else
-#define GETOPT "ah:n:rtu"
-#define USAGE "[-artu] [-n num_servers] [-h bindip]"
-#endif
+ cltpflag = unregister = reregister = tcpflag = 0;
+ bindanyflag = udpflag = ip6flag = 0;
+#define GETOPT "ah:n:rdtu"
+#define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
while ((ch = getopt(argc, argv, GETOPT)) != -1)
switch (ch) {
case 'a':
@@ -221,25 +221,15 @@ main(argc, argv, envp)
case 'r':
reregister = 1;
break;
+ case 'd':
+ unregister = 1;
+ break;
case 't':
tcpflag = 1;
break;
case 'u':
udpflag = 1;
break;
-#ifdef ISO
- case 'c':
- cltpflag = 1;
- break;
-#ifdef notyet
- case 'i':
- tp4cnt = 1;
- break;
- case 'p':
- tpipcnt = 1;
- break;
-#endif /* notyet */
-#endif /* ISO */
default:
case '?':
usage();
@@ -263,6 +253,13 @@ main(argc, argv, envp)
nfsdcnt = DEFNFSDCNT;
}
}
+ ip6flag = 1;
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0 && (errno == EPROTONOSUPPORT ||
+ errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
+ ip6flag = 0;
+ else
+ close(s);
if (bindhostc == 0 || bindanyflag) {
bindhostc++;
@@ -278,33 +275,126 @@ main(argc, argv, envp)
daemon(0, 0);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGSYS, nonfs);
+ (void)signal(SIGUSR1, cleanup);
+ /*
+ * nfsd sits in the kernel most of the time. It needs
+ * to ignore SIGTERM/SIGQUIT in order to stay alive as long
+ * as possible during a shutdown, otherwise loopback
+ * mounts will not be able to unmount.
+ */
(void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
}
(void)signal(SIGCHLD, reapchild);
-
+ if (unregister) {
+ unregistration();
+ exit (0);
+ }
if (reregister) {
- if (udpflag &&
- (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
- err(1, "can't register with portmap for UDP");
- if (tcpflag &&
- (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
- err(1, "can't register with portmap for TCP");
- exit(0);
+ if (udpflag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp = getnetconfigent("udp");
+ if (nconf_udp == NULL)
+ err(1, "getnetconfigent udp failed");
+ nb_udp.buf = ai_udp->ai_addr;
+ nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
+ err(1, "rpcb_set udp failed");
+ freeaddrinfo(ai_udp);
+ }
+ if (udpflag && ip6flag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp6 = getnetconfigent("udp6");
+ if (nconf_udp6 == NULL)
+ err(1, "getnetconfigent udp6 failed");
+ nb_udp6.buf = ai_udp6->ai_addr;
+ nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
+ err(1, "rpcb_set udp6 failed");
+ freeaddrinfo(ai_udp6);
+ }
+ if (tcpflag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp = getnetconfigent("tcp");
+ if (nconf_tcp == NULL)
+ err(1, "getnetconfigent tcp failed");
+ nb_tcp.buf = ai_tcp->ai_addr;
+ nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
+ err(1, "rpcb_set tcp failed");
+ freeaddrinfo(ai_tcp);
+ }
+ if (tcpflag && ip6flag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp6 = getnetconfigent("tcp6");
+ if (nconf_tcp6 == NULL)
+ err(1, "getnetconfigent tcp6 failed");
+ nb_tcp6.buf = ai_tcp6->ai_addr;
+ nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
+ err(1, "rpcb_set tcp6 failed");
+ freeaddrinfo(ai_tcp6);
+ }
+ exit (0);
}
+
openlog("nfsd:", LOG_PID, LOG_DAEMON);
for (i = 0; i < nfsdcnt; i++) {
- switch (fork()) {
+ switch ((pid = fork())) {
case -1:
syslog(LOG_ERR, "fork: %m");
+ killchildren();
exit (1);
case 0:
break;
default:
+ children[i] = pid;
continue;
}
@@ -399,182 +489,295 @@ main(argc, argv, envp)
exit(0);
}
- /* If we are serving udp, set up the socket. */
- for (i = 0; udpflag && i < bindhostc; i++) {
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create udp socket");
- exit(1);
- }
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(sock,
- (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register with udp portmap");
- exit(1);
+ if (atexit(killchildren) == -1) {
+ syslog(LOG_ERR, "atexit: %s", strerror(errno));
+ exit(1);
+ }
+ FD_ZERO(&v4bits);
+ FD_ZERO(&v6bits);
+
+ rpcbregcnt = 0;
+ /* Set up the socket for udp and rpcb register it. */
+ if (udpflag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((sock = socket(ai_udp->ai_family,
+ ai_udp->ai_socktype,
+ ai_udp->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create udp socket");
+ exit(1);
+ }
+ if (bind(sock, ai_udp->ai_addr,
+ ai_udp->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind udp addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ freeaddrinfo(ai_udp);
+ nfsdargs.sock = sock;
+ nfsdargs.name = NULL;
+ nfsdargs.namelen = 0;
+ if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+ syslog(LOG_ERR, "can't Add UDP socket");
+ exit(1);
+ }
+ (void)close(sock);
+ }
}
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR, "can't Add UDP socket");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp = getnetconfigent("udp");
+ if (nconf_udp == NULL)
+ err(1, "getnetconfigent udp failed");
+ nb_udp.buf = ai_udp->ai_addr;
+ nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
+ err(1, "rpcb_set udp failed");
+ freeaddrinfo(ai_udp);
}
- (void)close(sock);
}
-#ifdef ISO
- /* If we are serving cltp, set up the socket. */
- if (cltpflag) {
- if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create cltp socket");
- exit(1);
- }
- memset(&isoaddr, 0, sizeof(isoaddr));
- isoaddr.siso_family = AF_ISO;
- isoaddr.siso_tlen = 2;
- cp = TSEL(&isoaddr);
- *cp++ = (NFS_PORT >> 8);
- *cp = (NFS_PORT & 0xff);
- isoaddr.siso_len = sizeof(isoaddr);
- if (bind(sock,
- (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
- syslog(LOG_ERR, "can't bind cltp addr");
- exit(1);
- }
-#ifdef notyet
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register with udp portmap");
- exit(1);
+ /* Set up the socket for udp6 and rpcb register it. */
+ if (udpflag && ip6flag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((sock = socket(ai_udp6->ai_family,
+ ai_udp6->ai_socktype,
+ ai_udp6->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create udp6 socket");
+ exit(1);
+ }
+ if (setsockopt(sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY,
+ &on, sizeof on) < 0) {
+ syslog(LOG_ERR,
+ "can't set v6-only binding for "
+ "udp6 socket: %m");
+ exit(1);
+ }
+ if (bind(sock, ai_udp6->ai_addr,
+ ai_udp6->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind udp6 addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ freeaddrinfo(ai_udp6);
+ nfsdargs.sock = sock;
+ nfsdargs.name = NULL;
+ nfsdargs.namelen = 0;
+ if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+ syslog(LOG_ERR,
+ "can't add UDP6 socket");
+ exit(1);
+ }
+ (void)close(sock);
+ }
}
-#endif /* notyet */
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR, "can't add UDP socket");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp6 = getnetconfigent("udp6");
+ if (nconf_udp6 == NULL)
+ err(1, "getnetconfigent udp6 failed");
+ nb_udp6.buf = ai_udp6->ai_addr;
+ nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
+ err(1, "rpcb_set udp6 failed");
+ freeaddrinfo(ai_udp6);
}
- close(sock);
}
-#endif /* ISO */
-
- /* Now set up the master server socket waiting for tcp connections. */
- on = 1;
- FD_ZERO(&sockbits);
- connect_type_cnt = 0;
- for (i = 0; tcpflag && i < bindhostc; i++) {
- if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create tcp socket");
- exit(1);
- }
- if (setsockopt(tcpsock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(tcpsock,
- (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (listen(tcpsock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
+
+ /* Set up the socket for tcp and rpcb register it. */
+ if (tcpflag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((tcpsock = socket(AF_INET, SOCK_STREAM,
+ 0)) < 0) {
+ syslog(LOG_ERR,
+ "can't create tpc socket");
+ exit(1);
+ }
+ if (setsockopt(tcpsock, SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_REUSEADDR: %m");
+ if (bind(tcpsock, ai_tcp->ai_addr,
+ ai_tcp->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind tcp addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ if (listen(tcpsock, 5) < 0) {
+ syslog(LOG_ERR, "listen failed");
+ exit(1);
+ }
+ freeaddrinfo(ai_tcp);
+ FD_SET(tcpsock, &sockbits);
+ FD_SET(tcpsock, &v4bits);
+ maxsock = tcpsock;
+ connect_type_cnt++;
+ }
}
- if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints,
+ &ai_tcp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp = getnetconfigent("tcp");
+ if (nconf_tcp == NULL)
+ err(1, "getnetconfigent tcp failed");
+ nb_tcp.buf = ai_tcp->ai_addr;
+ nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
+ &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
+ nconf_tcp, &nb_tcp)))
+ err(1, "rpcb_set tcp failed");
+ freeaddrinfo(ai_tcp);
}
- FD_SET(tcpsock, &sockbits);
- maxsock = tcpsock;
- connect_type_cnt++;
}
-#ifdef notyet
- /* Now set up the master server socket waiting for tp4 connections. */
- if (tp4flag) {
- if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
- syslog(LOG_ERR, "can't create tp4 socket");
- exit(1);
- }
- if (setsockopt(tp4sock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- memset(&isoaddr, 0, sizeof(isoaddr));
- isoaddr.siso_family = AF_ISO;
- isoaddr.siso_tlen = 2;
- cp = TSEL(&isoaddr);
- *cp++ = (NFS_PORT >> 8);
- *cp = (NFS_PORT & 0xff);
- isoaddr.siso_len = sizeof(isoaddr);
- if (bind(tp4sock,
- (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tp4 addr");
- exit(1);
- }
- if (listen(tp4sock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
+ /* Set up the socket for tcp6 and rpcb register it. */
+ if (tcpflag && ip6flag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((tcp6sock = socket(ai_tcp6->ai_family,
+ ai_tcp6->ai_socktype,
+ ai_tcp6->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create tcp6 socket");
+ exit(1);
+ }
+ if (setsockopt(tcp6sock, SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_REUSEADDR: %m");
+ if (setsockopt(tcp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
+ syslog(LOG_ERR,
+ "can't set v6-only binding for tcp6 "
+ "socket: %m");
+ exit(1);
+ }
+ if (bind(tcp6sock, ai_tcp6->ai_addr,
+ ai_tcp6->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind tcp6 addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ if (listen(tcp6sock, 5) < 0) {
+ syslog(LOG_ERR, "listen failed");
+ exit(1);
+ }
+ freeaddrinfo(ai_tcp6);
+ FD_SET(tcp6sock, &sockbits);
+ FD_SET(tcp6sock, &v6bits);
+ if (maxsock < tcp6sock)
+ maxsock = tcp6sock;
+ connect_type_cnt++;
+ }
}
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp6 = getnetconfigent("tcp6");
+ if (nconf_tcp6 == NULL)
+ err(1, "getnetconfigent tcp6 failed");
+ nb_tcp6.buf = ai_tcp6->ai_addr;
+ nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
+ err(1, "rpcb_set tcp6 failed");
+ freeaddrinfo(ai_tcp6);
}
- FD_SET(tp4sock, &sockbits);
- maxsock = tp4sock;
- connect_type_cnt++;
}
- /* Now set up the master server socket waiting for tpip connections. */
- for (i = 0; tpipflag && i < bindhostc; i++) {
- if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
- syslog(LOG_ERR, "can't create tpip socket");
- exit(1);
- }
- if (setsockopt(tpipsock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(tpipsock,
- (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (listen(tpipsock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
- }
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
- }
- FD_SET(tpipsock, &sockbits);
- maxsock = tpipsock;
- connect_type_cnt++;
+ if (rpcbregcnt == 0) {
+ syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
+ exit(1);
}
-#endif /* notyet */
- if (connect_type_cnt == 0)
- exit(0);
+ if ((tcpflag) && (connect_type_cnt == 0)) {
+ syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
+ exit(1);
+ }
setproctitle("master");
@@ -591,82 +794,94 @@ main(argc, argv, envp)
exit(1);
}
}
- if (tcpflag && FD_ISSET(tcpsock, &ready)) {
- len = sizeof(inetpeer);
- if ((msgsock = accept(tcpsock,
- (struct sockaddr *)&inetpeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
- }
- memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inetpeer;
- nfsdargs.namelen = sizeof(inetpeer);
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- }
-#ifdef notyet
- if (tp4flag && FD_ISSET(tp4sock, &ready)) {
- len = sizeof(isopeer);
- if ((msgsock = accept(tp4sock,
- (struct sockaddr *)&isopeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
- }
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&isopeer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- }
- if (tpipflag && FD_ISSET(tpipsock, &ready)) {
- len = sizeof(inetpeer);
- if ((msgsock = accept(tpipsock,
- (struct sockaddr *)&inetpeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
+ for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
+ if (FD_ISSET(tcpsock, &ready)) {
+ if (FD_ISSET(tcpsock, &v4bits)) {
+ len = sizeof(inetpeer);
+ if ((msgsock = accept(tcpsock,
+ (struct sockaddr *)&inetpeer, &len)) < 0) {
+ syslog(LOG_ERR, "accept failed: %m");
+ exit(1);
+ }
+ memset(inetpeer.sin_zero, 0,
+ sizeof(inetpeer.sin_zero));
+ if (setsockopt(msgsock, SOL_SOCKET,
+ SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_KEEPALIVE: %m");
+ nfsdargs.sock = msgsock;
+ nfsdargs.name = (caddr_t)&inetpeer;
+ nfsdargs.namelen = sizeof(inetpeer);
+ nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+ (void)close(msgsock);
+ } else if (FD_ISSET(tcpsock, &v6bits)) {
+ len = sizeof(inet6peer);
+ if ((msgsock = accept(tcpsock,
+ (struct sockaddr *)&inet6peer,
+ &len)) < 0) {
+ syslog(LOG_ERR,
+ "accept failed: %m");
+ exit(1);
+ }
+ if (setsockopt(msgsock, SOL_SOCKET,
+ SO_KEEPALIVE, (char *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_ERR, "setsockopt "
+ "SO_KEEPALIVE: %m");
+ nfsdargs.sock = msgsock;
+ nfsdargs.name = (caddr_t)&inet6peer;
+ nfsdargs.namelen = sizeof(inet6peer);
+ nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+ (void)close(msgsock);
+ }
}
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inetpeer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
}
-#endif /* notyet */
}
}
-void
-setbindhost(struct sockaddr_in *ia, const char *bindhost)
+int
+setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
{
- ia->sin_family = AF_INET;
- ia->sin_port = htons(NFS_PORT);
- ia->sin_len = sizeof(*ia);
- if (bindhost == NULL || strcmp(bindhost,"*") == 0) {
- ia->sin_addr.s_addr = INADDR_ANY;
- } else {
- if (inet_aton(bindhost, &ia->sin_addr) == 0) {
- struct hostent *he;
-
- he = gethostbyname2(bindhost, ia->sin_family);
- if (he == NULL) {
- syslog(LOG_ERR, "gethostbyname of %s failed", bindhost);
- exit(1);
+ int ecode;
+ u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ const char *hostptr;
+
+ if (bindhost == NULL || strcmp("*", bindhost) == 0)
+ hostptr = NULL;
+ else
+ hostptr = bindhost;
+
+ if (hostptr != NULL) {
+ switch (hints.ai_family) {
+ case AF_INET:
+ if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
+ hints.ai_flags = AI_NUMERICHOST;
+ } else {
+ if (inet_pton(AF_INET6, hostptr,
+ host_addr) == 1)
+ return (1);
+ }
+ break;
+ case AF_INET6:
+ if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
+ hints.ai_flags = AI_NUMERICHOST;
+ } else {
+ if (inet_pton(AF_INET, hostptr,
+ host_addr) == 1)
+ return (1);
}
- bcopy(he->h_addr, &ia->sin_addr, he->h_length);
+ break;
+ default:
}
}
+
+ ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
+ gai_strerror(ecode));
+ return (1);
+ }
+ return (0);
}
void
@@ -691,6 +906,48 @@ reapchild(signo)
while (wait3(NULL, WNOHANG, NULL) > 0);
}
+void
+unregistration()
+{
+ if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
+ (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
+ syslog(LOG_ERR, "rpcb_unset failed");
+}
+
+void
+killchildren()
+{
+ int i;
+ sigset_t sigs;
+
+ sigemptyset(&sigs);
+ /*
+ * Block SIGCHLD to avoid killing a reaped process (although it is
+ * unlikely, the pid might have been reused).
+ */
+ sigaddset(&sigs, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) {
+ syslog(LOG_ERR, "sigprocmask: %s",
+ strerror(errno));
+ return;
+ }
+ for (i = 0; i < nfsdcnt; i++) {
+ if (children[i] > 0)
+ kill(children[i], SIGKILL);
+ }
+ if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) {
+ syslog(LOG_ERR, "sigprocmask: %s", strerror(errno));
+ }
+ unregistration();
+}
+
+void
+cleanup(signo)
+{
+ killchildren();
+ exit (0);
+}
+
#ifdef OLD_SETPROCTITLE
#ifdef __FreeBSD__
void
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index e9ef990cc2d2..2a3a3373e2e5 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -47,6 +47,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/socket.h>
#include <netdb.h>
#include <rpc/rpc.h>
@@ -68,6 +69,7 @@ typedef enum { MNTON, MNTFROM, NOTHING } mntwhat;
typedef enum { MARK, UNMARK, NAME, COUNT, FREE } dowhat;
struct mtablist *mtabhead;
+struct addrinfo *nfshost_ai = NULL;
int fflag, vflag;
char *nfshost;
@@ -78,19 +80,22 @@ char *getmntname (const char *, const char *,
char *getrealname(char *, char *resolved_path);
char **makevfslist (const char *);
size_t mntinfo (struct statfs **);
-int namematch (struct hostent *);
+int namematch (struct addrinfo *);
+int sacmp (struct sockaddr *, struct sockaddr *);
int umountall (char **);
-int umountfs (char *, char **);
+int checkname (char *, char **);
+int umountfs (char *, char *, char *);
void usage (void);
int xdr_dir (XDR *, char *);
int
main(int argc, char *argv[])
{
- int all, errs, ch, mntsize;
+ int all, errs, ch, mntsize, error;
char **typelist = NULL, *mntonname, *mntfromname;
char *type, *mntfromnamerev, *mntonnamerev;
struct statfs *mntbuf;
+ struct addrinfo hints;
/* Start disks transferring immediately. */
sync();
@@ -133,6 +138,15 @@ main(int argc, char *argv[])
if ((nfshost != NULL) && (typelist == NULL))
typelist = makevfslist("nfs");
+ if (nfshost != NULL) {
+ memset(&hints, 0, sizeof hints);
+ error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai);
+ if (error) {
+ fprintf(stderr, "ndp: %s: %s\n", nfshost,
+ gai_strerror(error));
+ }
+ }
+
switch (all) {
case 2:
if ((mntsize = mntinfo(&mntbuf)) <= 0)
@@ -165,7 +179,7 @@ main(int argc, char *argv[])
"is mounted there, umount it first",
mntonname, mntfromnamerev);
- if (umountfs(mntbuf[mntsize].f_mntonname,
+ if (checkname(mntbuf[mntsize].f_mntonname,
typelist) != 0)
errs = 1;
}
@@ -178,7 +192,7 @@ main(int argc, char *argv[])
break;
case 0:
for (errs = 0; *argv != NULL; ++argv)
- if (umountfs(*argv, typelist) != 0)
+ if (checkname(*argv, typelist) != 0)
errs = 1;
break;
}
@@ -228,33 +242,29 @@ umountall(char **typelist)
err(1, "malloc failed");
(void)strcpy(cp, fs->fs_file);
rval = umountall(typelist);
- rval = umountfs(cp, typelist) || rval;
+ rval = checkname(cp, typelist) || rval;
free(cp);
return (rval);
} while ((fs = getfsent()) != NULL);
return (0);
}
+/*
+ * Do magic checks on mountpoint and device or hand over
+ * it to unmount(2) if everything fails.
+ */
int
-umountfs(char *name, char **typelist)
+checkname(char *name, char **typelist)
{
- enum clnt_stat clnt_stat;
- struct hostent *hp;
- struct mtablist *mtab;
- struct sockaddr_in saddr;
- struct timeval pertry, try;
- CLIENT *clp;
size_t len;
- int so, speclen, do_rpc;
+ int speclen;
char *mntonname, *mntfromname;
char *mntfromnamerev;
- char *nfsdirname, *orignfsdirname;
char *resolved, realname[MAXPATHLEN];
- char *type, *delimp, *hostp, *origname;
+ char *type, *hostp, *delimp, *origname;
len = 0;
- mtab = NULL;
- mntfromname = mntonname = delimp = hostp = orignfsdirname = NULL;
+ mntfromname = mntonname = delimp = hostp = NULL;
/*
* 1. Check if the name exists in the mounttable.
@@ -323,14 +333,29 @@ umountfs(char *name, char **typelist)
resolved = realname;
}
/*
- * All tests failed, return to main()
+ * 5. All tests failed, just hand over the
+ * mountpoint to the kernel, maybe the statfs
+ * structure has been truncated or is not
+ * useful anymore because of a chroot(2).
+ * Please note that nfs will not be able to
+ * notify the nfs-server about unmounting.
+ * These things can change in future when the
+ * fstat structure get's more reliable,
+ * but at the moment we cannot thrust it.
*/
if (mntfromname == NULL && mntonname == NULL) {
(void)strcpy(name, origname);
- warnx("%s: not currently mounted",
- origname);
- free(origname);
- return (1);
+ if (umountfs(NULL, origname,
+ "none") == 0) {;
+ warnx("%s not found in "
+ "mount table, "
+ "unmounted it anyway",
+ origname);
+ free(origname);
+ return (0);
+ } else
+ free(origname);
+ return (1);
}
}
}
@@ -341,21 +366,6 @@ umountfs(char *name, char **typelist)
if (checkvfsname(type, typelist))
return (1);
- hp = NULL;
- nfsdirname = NULL;
- if (!strcmp(type, "nfs")) {
- if ((nfsdirname = strdup(mntfromname)) == NULL)
- err(1, "strdup");
- orignfsdirname = nfsdirname;
- if ((delimp = strchr(nfsdirname, ':')) != NULL) {
- *delimp = '\0';
- hostp = nfsdirname;
- if ((hp = gethostbyname(hostp)) == NULL) {
- warnx("can't get net id for host");
- }
- nfsdirname = delimp + 1;
- }
- }
/*
* Check if the reverse entrys of the mounttable are really the
* same as the normal ones.
@@ -383,6 +393,43 @@ umountfs(char *name, char **typelist)
return (1);
}
free(mntfromnamerev);
+ umountfs(mntfromname, mntonname, type);
+}
+
+/*
+ * NFS stuff and unmount(2) call
+ */
+int
+umountfs(char *mntfromname, char *mntonname, char *type)
+{
+ enum clnt_stat clnt_stat;
+ struct timeval try;
+ struct mtablist *mtab;
+ struct addrinfo *ai, hints;
+ int do_rpc;
+ CLIENT *clp;
+ char *nfsdirname, *orignfsdirname;
+ char *hostp, *delimp;
+
+ mtab = NULL;
+ ai = NULL;
+ nfsdirname = delimp = orignfsdirname = NULL;
+ memset(&hints, 0, sizeof hints);
+
+ if (!strcmp(type, "nfs")) {
+ if ((nfsdirname = strdup(mntfromname)) == NULL)
+ err(1, "strdup");
+ orignfsdirname = nfsdirname;
+ if ((delimp = strrchr(nfsdirname, ':')) != NULL) {
+ *delimp = '\0';
+ hostp = nfsdirname;
+ getaddrinfo(hostp, NULL, &hints, &ai);
+ if (ai == NULL) {
+ warnx("can't get net id for host");
+ }
+ nfsdirname = delimp + 1;
+ }
+ }
/*
* Check if we have to start the rpc-call later.
* If there are still identical nfs-names mounted,
@@ -395,7 +442,8 @@ umountfs(char *name, char **typelist)
do_rpc = 1;
else
do_rpc = 0;
- if (!namematch(hp))
+
+ if (!namematch(ai))
return (1);
if (unmount(mntonname, fflag) != 0 ) {
warn("unmount of %s failed", mntonname);
@@ -407,21 +455,13 @@ umountfs(char *name, char **typelist)
* Report to mountd-server which nfsname
* has been unmounted.
*/
- if (hp != NULL && !(fflag & MNT_FORCE) && do_rpc) {
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
- memmove(&saddr.sin_addr, hp->h_addr,
- MIN(hp->h_length, sizeof(saddr.sin_addr)));
- pertry.tv_sec = 3;
- pertry.tv_usec = 0;
- so = RPC_ANYSOCK;
- if ((clp = clntudp_create(&saddr,
- RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) {
+ if (ai != NULL && !(fflag & MNT_FORCE) && do_rpc) {
+ clp = clnt_create(hostp, RPCPROG_MNT, RPCMNT_VER1, "udp");
+ if (clp == NULL) {
clnt_pcreateerror("Cannot MNT PRC");
return (1);
}
- clp->cl_auth = authunix_create_default();
+ clp->cl_auth = authsys_create_default();
try.tv_sec = 20;
try.tv_usec = 0;
clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir,
@@ -554,30 +594,53 @@ getmntname(const char *fromname, const char *onname,
}
int
-namematch(struct hostent *hp)
+sacmp(struct sockaddr *sa1, struct sockaddr *sa2)
{
- char *cp, **np;
+ void *p1, *p2;
+ int len;
- if ((hp == NULL) || (nfshost == NULL))
+ if (sa1->sa_family != sa2->sa_family)
return (1);
- if (strcasecmp(nfshost, hp->h_name) == 0)
- return (1);
-
- if ((cp = strchr(hp->h_name, '.')) != NULL) {
- *cp = '\0';
- if (strcasecmp(nfshost, hp->h_name) == 0)
+ switch (sa1->sa_family) {
+ case AF_INET:
+ p1 = &((struct sockaddr_in *)sa1)->sin_addr;
+ p2 = &((struct sockaddr_in *)sa2)->sin_addr;
+ len = 4;
+ break;
+ case AF_INET6:
+ p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
+ p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
+ len = 16;
+ if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
return (1);
+ break;
+ default:
+ return (1);
}
- for (np = hp->h_aliases; *np; np++) {
- if (strcasecmp(nfshost, *np) == 0)
- return (1);
- if ((cp = strchr(*np, '.')) != NULL) {
- *cp = '\0';
- if (strcasecmp(nfshost, *np) == 0)
+
+ return memcmp(p1, p2, len);
+}
+
+int
+namematch(struct addrinfo *ai)
+{
+ struct addrinfo *aip;
+
+ if (nfshost == NULL || nfshost_ai == NULL)
+ return (1);
+
+ while (ai != NULL) {
+ aip = nfshost_ai;
+ while (aip != NULL) {
+ if (sacmp(ai->ai_addr, aip->ai_addr) == 0)
return (1);
+ aip = aip->ai_next;
}
+ ai = ai->ai_next;
}
+
return (0);
}
diff --git a/sys/rpc/types.h b/sys/rpc/types.h
index e2ceec5b3df7..4a5c6564b270 100644
--- a/sys/rpc/types.h
+++ b/sys/rpc/types.h
@@ -1,3 +1,5 @@
+/* $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -37,8 +39,18 @@
#ifndef _RPC_TYPES_H
#define _RPC_TYPES_H
-#define bool_t int32_t
-#define enum_t int32_t
+#include <sys/types.h>
+
+typedef int32_t bool_t;
+typedef int32_t enum_t;
+
+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;
+
#define __dontcare__ -1
#ifndef FALSE
@@ -51,12 +63,46 @@
# define NULL 0
#endif
-#define mem_alloc(bsize) malloc(bsize)
+#define mem_alloc(bsize) calloc(1, bsize)
#define mem_free(ptr, bsize) free(ptr)
-#ifndef makedev /* ie, we haven't already included it */
-#include <sys/types.h>
-#endif
#include <sys/time.h>
+#include <netconfig.h>
+
+/*
+ * The netbuf structure is defined here, because FreeBSD / NetBSD only use
+ * it inside the RPC code. It's in <xti.h> on SVR4, but it would be confusing
+ * to have an xti.h, since FreeBSD / NetBSD does not support XTI/TLI.
+ */
+
+/*
+ * The netbuf structure is used for transport-independent address storage.
+ */
+struct netbuf {
+ unsigned int maxlen;
+ unsigned int len;
+ void *buf;
+};
+
+/*
+ * The format of the addres and options arguments of the XTI t_bind call.
+ * Only provided for compatibility, it should not be used.
+ */
+
+struct t_bind {
+ struct netbuf addr;
+ unsigned int qlen;
+};
+
+/*
+ * Internal library and rpcbind use. This is not an exported interface, do
+ * not use.
+ */
+struct __rpc_sockinfo {
+ int si_af;
+ int si_proto;
+ int si_socktype;
+ int si_alen;
+};
#endif /* !_RPC_TYPES_H */
diff --git a/usr.bin/keylogin/keylogin.c b/usr.bin/keylogin/keylogin.c
index 55529c85aeb8..15b62e1bce66 100644
--- a/usr.bin/keylogin/keylogin.c
+++ b/usr.bin/keylogin/keylogin.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -49,7 +50,7 @@ int
main()
{
char fullname[MAXNETNAMELEN + 1];
- struct netstarg netst;
+ struct key_netstarg netst;
if (!getnetname(fullname)) {
fprintf(stderr, "netname lookup failed -- make sure the ");
diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c
index 5e2ebf70d271..2674b3a8788b 100644
--- a/usr.bin/rpcgen/rpc_main.c
+++ b/usr.bin/rpcgen/rpc_main.c
@@ -152,11 +152,7 @@ int newstyle; /* newstyle of passing arguments (by value) */
int Cflag = 0; /* ANSI C syntax */
int CCflag = 0; /* C++ files */
static int allfiles; /* generate all files */
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-int tirpcflag = 0; /* generating code for tirpc, by default */
-#else
int tirpcflag = 1; /* generating code for tirpc, by default */
-#endif
xdrfunc *xdrfunc_head = NULL; /* xdr function list */
xdrfunc *xdrfunc_tail = NULL; /* xdr function list */
pid_t childpid;
@@ -692,9 +688,10 @@ s_output(argc, argv, infile, define, extend, outfile, nomain, netflag)
f_print(fout, "#include <memory.h>\n");
#if defined(__FreeBSD__) || defined(__NetBSD__)
+#else
if (tirpcflag)
-#endif
f_print(fout, "#include <stropts.h>\n");
+#endif
if (inetdflag || !tirpcflag) {
f_print(fout, "#include <sys/socket.h>\n");
f_print(fout, "#include <netinet/in.h>\n");
@@ -1173,11 +1170,7 @@ parseargs(argc, argv, cmd)
* generating backward compatible
* code
*/
-#if defined(__FreeBSD__) || defined(__NetBSD__)
- tirpcflag = 1;
-#else
tirpcflag = 0;
-#endif
break;
case 'I':
@@ -1273,9 +1266,7 @@ parseargs(argc, argv, cmd)
}
} else { /* 4.1 mode */
pmflag = 0; /* set pmflag only in tirpcmode */
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
inetdflag = 1; /* inetdflag is TRUE by default */
-#endif
if (cmd->nflag) { /* netid needs TIRPC */
warnx("cannot use netid flag without TIRPC");
return (0);
diff --git a/usr.bin/rpcgen/rpc_parse.c b/usr.bin/rpcgen/rpc_parse.c
index 1d952cc0eec2..a4a44c86014d 100644
--- a/usr.bin/rpcgen/rpc_parse.c
+++ b/usr.bin/rpcgen/rpc_parse.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -593,7 +594,11 @@ get_type(prefixp, typep, dkind)
(void) peekscan(TOK_INT, &tok);
break;
case TOK_HYPER:
+#ifdef __FreeBSD__
*typep = "int64_t";
+#else
+ *typep = "longlong_t";
+#endif
(void) peekscan(TOK_INT, &tok);
break;
@@ -642,7 +647,12 @@ unsigned_dec(typep)
break;
case TOK_HYPER:
get_token(&tok);
+#ifdef __FreeBSD__
*typep = "u_int64_t";
+#else
+ *typep = "longlong_t";
+#endif
+
(void) peekscan(TOK_INT, &tok);
break;
case TOK_INT:
diff --git a/usr.bin/rpcgen/rpc_svcout.c b/usr.bin/rpcgen/rpc_svcout.c
index 62b2ab1aa550..86ff5a260b94 100644
--- a/usr.bin/rpcgen/rpc_svcout.c
+++ b/usr.bin/rpcgen/rpc_svcout.c
@@ -1,4 +1,6 @@
/*
+ * $FreeBSD$
+ *
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
@@ -635,7 +637,7 @@ printif(proc, transp, prefix, arg)
char *prefix;
char *arg;
{
- f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n",
+ f_print(fout, "\tif (!svc_%s(%s, xdr_%s, (char *)%s%s)) {\n",
proc, transp, arg, prefix, arg);
}
diff --git a/usr.bin/rpcgen/rpcgen.1 b/usr.bin/rpcgen/rpcgen.1
index d8ecd96c0aa5..c00dda4bf187 100644
--- a/usr.bin/rpcgen/rpcgen.1
+++ b/usr.bin/rpcgen/rpcgen.1
@@ -233,7 +233,7 @@ If this routine does not exist in the
library, it must be provided.
Providing an undefined data type
allows customization of
-.Xr XDR
+.Xr xdr 3
routines.
.Sh OPTIONS
The following options are available:
@@ -246,15 +246,6 @@ Generate transport specific
.Tn RPC
code for older versions
of the operating system.
-.Pp
-Note: in
-.Fx ,
-this compatibility flag is turned on by
-default since
-.Fx
-supports only the older
-.Tn ONC RPC
-library.
.It Fl c
Compile into
.Tn XDR
@@ -510,9 +501,10 @@ use:
.Sh SEE ALSO
.Xr cc 1 ,
.Xr rpc 3 ,
+.Xr rpc_svc_calls 3 ,
.Xr syslog 3 ,
+.Xr xdr 3 ,
.Xr inetd 8
-.\" .BR rpc_svc_calls (3)
.Rs
.%T The rpcgen chapter in the NETP manual
.Re
diff --git a/usr.bin/rpcinfo/Makefile b/usr.bin/rpcinfo/Makefile
index 045c37cf1188..6c75c8f67135 100644
--- a/usr.bin/rpcinfo/Makefile
+++ b/usr.bin/rpcinfo/Makefile
@@ -2,7 +2,15 @@
# $FreeBSD$
PROG= rpcinfo
-MAN8 = rpcinfo.8
+MAN8= rpcinfo.8
+SRCS= rpcinfo.c rpc_generic.c
+LIBCDIR= ${.CURDIR}/../../lib/libc
+LIBCRPCDIR= ${LIBCDIR}/rpc
+LIBCINCLUDE= ${LIBCDIR}/include
+
+CFLAGS+= -I${LIBCRPCDIR} -I${LIBCINCLUDE} -DPORTMAP -DINET6
+
+.PATH: ${LIBCRPCDIR}
.include <bsd.prog.mk>
diff --git a/usr.bin/rpcinfo/rpcinfo.8 b/usr.bin/rpcinfo/rpcinfo.8
index 38da63093815..9976a14ce89f 100644
--- a/usr.bin/rpcinfo/rpcinfo.8
+++ b/usr.bin/rpcinfo/rpcinfo.8
@@ -1,7 +1,9 @@
-.\" from: @(#)rpcinfo.8c 2.2 88/08/03 4.0 RPCSRC; from 1.24 88/02/25 SMI
+.\" @(#)rpcinfo.1m 1.23 93/03/29 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $NetBSD: rpcinfo.8,v 1.6 2000/06/02 23:19:38 fvdl Exp $
.\" $FreeBSD$
-.\"
-.Dd December 17, 1987
+.Dd August 18, 1992
.Dt RPCINFO 8
.Os
.Sh NAME
@@ -9,158 +11,330 @@
.Nd report RPC information
.Sh SYNOPSIS
.Nm
-.Fl p
+.Op Fl m | s
.Op Ar host
.Nm
+.Op Ar host
+.Nm
+.Fl T Ar transport
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Fl l
+.Op Fl T Ar transport
+.Ar host prognum
+.Op Ar versnum
+.Nm
.Op Fl n Ar portnum
-.Fl u Ar host
-.Ar program
-.Op Ar version
+.Fl u
+.Ar host prognum
+.Op Ar versnum
.Nm
.Op Fl n Ar portnum
-.Fl t Ar host
-.Ar program
-.Op Ar version
+.Op Fl t
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Fl a Ar serv_address
+.Fl T Ar transport
+.Ar prognum
+.Op Ar versnum
.Nm
.Fl b
-.Ar program version
+.Op Fl T Ar transport
+.Ar prognum versnum
.Nm
.Fl d
-.Ar program version
+.Op Fl T Ar transport
+.Ar prognum versnum
.Sh DESCRIPTION
-.Nm Rpcinfo
-makes an
-.Tn RPC
-call to an
-.Tn RPC
+.Nm
+makes an RPC call to an RPC
server and reports what it finds.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl p
-Probe the portmapper on
-.Ar host ,
-and print a list of all registered
-.Tn RPC
-programs. If
-.Ar host
-is not specified, it defaults to the value returned by
-.Xr hostname 1 .
-.It Fl u
-Make an
-.Tn RPC
-call to procedure 0 of
-.Ar program
-on the specified
+.Pp
+In the first synopsis,
+.Nm
+lists all the registered RPC services with
+.Nm rpcbind
+on
+.Ar host .
+If
.Ar host
-using
-.Tn UDP ,
-and report whether a response was received.
-.It Fl t
-Make an
-.Tn RPC
-call to procedure 0 of
-.Ar program
+is not specified, the local host is the default.
+If
+.Fl s
+is used, the information is displayed in a concise format.
+.Pp
+In the second synopsis,
+.Nm
+lists all the RPC services registered with
+.Nm rpcbind ,
+version 2.
+Also note that the format of the information
+is different in the first and the second synopsis.
+This is because the second synopsis is an older protocol used to
+collect the information displayed (version 2 of the
+.Nm rpcbind
+protocol).
+.Pp
+The third synopsis makes an RPC call to procedure 0
+of
+.Ar prognum
+and
+.Ar versnum
on the specified
.Ar host
-using
-.Tn TCP ,
-and report whether a response was received.
-.It Fl n
-Use
-.Ar portnum
-as the port number for the
-.Fl t
-and
-.Fl u
-options instead of the port number given by the portmapper.
-.It Fl b
-Make an
-.Tn RPC
-broadcast to procedure 0 of the specified
-.Ar program
-and
-.Ar version
-using
-.Tn UDP
-and report all hosts that respond.
-.It Fl d
-Delete registration for the
-.Tn RPC
-service of the specified
-.Ar program
-and
-.Ar version .
-This option can be exercised only by the super-user.
-.El
+and reports whether a response was received.
+.Ar transport
+is the transport which has to be used for contacting the
+given service.
+The remote address of the service is obtained by
+making a call to the remote
+.Nm rpcbind .
.Pp
The
-.Ar program
-argument can be either a name or a number.
-.Pp
+.Ar prognum
+argument is a number that represents an RPC program number
If a
-.Ar version
+.Ar versnum
is specified,
.Nm
attempts to call that version of the specified
-.Ar program .
+.Ar prognum .
Otherwise,
.Nm
attempts to find all the registered version
numbers for the specified
-.Ar program
-by calling version 0 (which is presumed not
-to exist; if it does exist,
+.Ar prognum
+by calling version 0,
+which is presumed not to exist;
+if it does exist,
.Nm
attempts to obtain this information by calling
-an extremely high version
-number instead) and attempts to call each registered version.
-Note: the version number is required for
+an extremely high version number instead,
+and attempts to call each registered version.
+Note:
+the version number is required for
.Fl b
and
.Fl d
options.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl T Ar transport
+Specify the transport on which the service is required.
+If this option is not specified,
+.Nm
+uses the transport specified in the
+.Ev NETPATH
+environment variable, or if that is unset or empty, the transport
+in the
+.Xr netconfig 5
+database is used.
+This is a generic option,
+and can be used in conjunction with other options as
+shown in the
+.Sx SYNOPSIS .
+.It Fl a Ar serv_address
+Use
+.Ar serv_address
+as the (universal) address for the service on
+.Ar transport
+to ping procedure 0
+of the specified
+.Ar prognum
+and report whether a response was received.
+The
+.Fl T
+option is required with the
+.Fl a
+option.
+.Pp
+If
+.Ar versnum
+is not specified,
+.Nm
+tries to ping all
+available version numbers for that program number.
+This option avoids calls to remote
+.Nm rpcbind
+to find the address of the service.
+The
+.Ar serv_address
+is specified in universal address format of the given transport.
+.It Fl b
+Make an RPC broadcast to procedure 0
+of the specified
+.Ar prognum
+and
+.Ar versnum
+and report all hosts that respond.
+If
+.Ar transport
+is specified, it broadcasts its request only on the
+specified transport.
+If broadcasting is not supported by any
+transport,
+an error message is printed.
+Use of broadcasting should be limited because of the potential for adverse
+effect on other systems.
+.It Fl d
+Delete registration for the RPC service of the specified
+.Ar prognum
+and
+.Ar versnum .
+If
+.Ar transport
+is specified,
+unregister the service on only that transport,
+otherwise unregister the service on all
+the transports on which it was registered.
+Only the owner of a service can delete a registration, except the
+super-user who can delete any service.
+.It Fl l
+Display a list of entries with a given
+.Ar prognum
+and
+.Ar versnum
+on the specified
+.Ar host .
+Entries are returned for all transports
+in the same protocol family as that used to contact the remote
+.Nm rpcbind .
+.It Fl m
+Display a table of statistics of
+.Nm rpcbind
+operations on the given
+.Ar host .
+The table shows statistics for each version of
+.Nm rpcbind
+(versions 2, 3 and 4), giving the number of times each procedure was
+requested and successfully serviced, the number and type of remote call
+requests that were made, and information about RPC address lookups that were
+handled.
+This is useful for monitoring RPC activities on
+.Ar host .
+.It Fl n Ar portnum
+Use
+.Ar portnum
+as the port number for the
+.Fl t
+and
+.Fl u
+options instead of the port number given by
+.Nm rpcbind .
+Use of this option avoids a call to the remote
+.Nm rpcbind
+to find out the address of the service.
+This option is made
+obsolete by the
+.Fl a
+option.
+.It Fl p
+Probe
+.Nm rpcbind
+on
+.Ar host
+using version 2 of the
+.Nm rpcbind
+protocol,
+and display a list of all registered RPC programs.
+If
+.Ar host
+is not specified, it defaults to the local host.
+Note: Version 2 of the
+.Nm rpcbind
+protocol was previously known as the portmapper protocol.
+.It Fl s
+Display a concise list of all registered RPC programs on
+.Ar host .
+If
+.Ar host
+is not specified, it defaults to the local host.
+.It Fl t
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using TCP,
+and report whether a response was received.
+This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.It Fl u
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using UDP,
+and report whether a response was received.
+This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.El
.Sh EXAMPLES
-To show all of the
-.Tn RPC
-services registered on the local machine use:
+To show all of the RPC services registered on the local machine use:
.Pp
-.Dl example% rpcinfo -p
+.Dl "example% rpcinfo"
.Pp
-To show all of the
-.Tn RPC
-services registered on the machine named
-.Ar klaxon
+To show all of the RPC
+services registered with
+.Nm rpcbind
+on the machine named
+.Dq klaxon
use:
.Pp
-.Dl example% rpcinfo -p klaxon
+.Dl "example% rpcinfo klaxon"
+.Pp
+The information displayed by the above commands can be quite lengthy.
+Use the
+.Fl s
+option to display a more concise list:
+.Pp
+.Dl "example$ rpcinfo -s klaxon"
+.Bl -column "program" "version(s)" "unix,tcp,udp,tcp6,udp6" "nlockmgr" "super-user"
+.It "program version(s) netid(s) service owner"
+.It "100000 2,3,4 unix,tcp,udp,tcp6,udp6 rpcbind super-user"
+.It "100008 1 udp,tcp,udp6,tcp6 walld super-user"
+.It "100002 2,1 udp,udp6 rusersd super-user"
+.It "100001 2,3,4 udp,udp6 rstatd super-user"
+.It "100012 1 udp,tcp sprayd super-user"
+.It "100007 3 udp,tcp ypbind super-user"
+.El
+.Pp
+To show whether the RPC
+service with program number
+.Ar prognum
+and version
+.Ar versnum
+is
+registered on the machine named
+.Dq klaxon
+for the transport TCP
+use:
.Pp
-To show all machines on the local net that are running the Yellow Pages
-service use:
+.Dl "example% rpcinfo -T tcp klaxon prognum versnum"
.Pp
-.Dl example% rpcinfo -b ypserv 'version' | uniq
+To show all RPC
+services registered with version 2 of the
+.Nm rpcbind
+protocol on the local machine use:
.Pp
-where 'version' is the current Yellow Pages version obtained from the
-results of the
-.Fl p
-switch above.
+.Dl "example% rpcinfo -p"
.Pp
-To delete the registration for version 1 of the
+To delete the registration for version
+1 of the
.Nm walld
-service use:
+(program number 100008)
+service for all transports use:
.Pp
-.Dl example% rpcinfo -d walld 1
+.Dl "example# rpcinfo -d 100008 1"
+or
+.Dl "example# rpcinfo -d walld 1"
.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr netconfig 5 ,
.Xr rpc 5 ,
-.Xr portmap 8
-.Rs
-.%T "RPC Programming Guide"
-.Re
-.Sh BUGS
-In releases prior to SunOS 3.0, the Network File System (NFS) did not
-register itself with the portmapper;
-.Nm
-cannot be used to make
-.Tn RPC
-calls to the
-.Tn NFS
-server on hosts running such releases.
+.Xr rpcbind 8
diff --git a/usr.bin/rpcinfo/rpcinfo.c b/usr.bin/rpcinfo/rpcinfo.c
index 622ea819a0c2..38abe2f7f11b 100644
--- a/usr.bin/rpcinfo/rpcinfo.c
+++ b/usr.bin/rpcinfo/rpcinfo.c
@@ -1,18 +1,5 @@
-#ifndef lint
-/*static char sccsid[] = "from: @(#)rpcinfo.c 1.22 87/08/12 SMI";*/
-/*static char sccsid[] = "from: @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC";*/
-static char rcsid[] =
- "$FreeBSD$";
-#endif
-
-/*
- * Copyright (C) 1986, Sun Microsystems, Inc.
- */
-
-/*
- * rpcinfo: ping a particular rpc program
- * or dump the portmapper
- */
+/* $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $ */
+/* $FreeBSD$ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
@@ -43,36 +30,64 @@ static char rcsid[] =
* Mountain View, California 94043
*/
-#include <err.h>
-#include <ctype.h>
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcinfo.c 1.18 93/07/05 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)rpcinfo.c 1.16 89/04/05 Copyr 1986 Sun Micro";
+#endif
+#endif
+
+/*
+ * rpcinfo: ping a particular rpc program
+ * or dump the the registered programs on the remote machine.
+ */
+
+/*
+ * We are for now defining PORTMAP here. It doesnt even compile
+ * unless it is defined.
+ */
+#ifndef PORTMAP
+#define PORTMAP
+#endif
+
+/*
+ * If PORTMAP is defined, rpcinfo will talk to both portmapper and
+ * rpcbind programs; else it talks only to rpcbind. In the latter case
+ * all the portmapper specific options such as -u, -t, -p become void.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <rpc/rpc.h>
#include <stdio.h>
-#include <sys/socket.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/rpcent.h>
+#include <rpc/nettype.h>
+#include <rpc/rpc_com.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <ctype.h>
+
+#ifdef PORTMAP /* Support for version 2 portmapper */
+#include <netinet/in.h>
#include <netdb.h>
+#include <arpa/inet.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
-#include <signal.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <arpa/inet.h>
+#endif
#define MAXHOSTLEN 256
-
#define MIN_VERS ((u_long) 0)
#define MAX_VERS ((u_long) 4294967295UL)
-
-static void udpping(/*u_short portflag, int argc, char **argv*/);
-static void tcpping(/*u_short portflag, int argc, char **argv*/);
-static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
-static void pmapdump(/*int argc, char **argv*/);
-static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/);
-static void brdcst(/*int argc, char **argv*/);
-static void deletereg(/* int argc, char **argv */) ;
-static void usage(/*void*/);
-static u_long getprognum(/*char *arg*/);
-static u_long getvers(/*char *arg*/);
-static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
+#define UNKNOWN "unknown"
/*
* Functions to be performed.
@@ -81,25 +96,90 @@ static void get_inet_address(/*struct sockaddr_in *addr, char *host*/);
#define PMAPDUMP 1 /* dump portmapper registrations */
#define TCPPING 2 /* ping TCP service */
#define UDPPING 3 /* ping UDP service */
-#define BRDCST 4 /* ping broadcast UDP service */
-#define DELETES 5 /* delete registration for the service */
+#define BROADCAST 4 /* ping broadcast service */
+#define DELETES 5 /* delete registration for the service */
+#define ADDRPING 6 /* pings at the given address */
+#define PROGPING 7 /* pings a program on a given host */
+#define RPCBDUMP 8 /* dump rpcbind registrations */
+#define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */
+#define RPCBADDRLIST 10 /* dump addr list about one prog */
+#define RPCBGETSTAT 11 /* Get statistics */
+
+struct netidlist {
+ char *netid;
+ struct netidlist *next;
+};
+
+struct verslist {
+ int vers;
+ struct verslist *next;
+};
+
+struct rpcbdump_short {
+ u_long prog;
+ struct verslist *vlist;
+ struct netidlist *nlist;
+ struct rpcbdump_short *next;
+ char *owner;
+};
+
+
+
+#ifdef PORTMAP
+static void ip_ping(u_short, char *, int, char **);
+static CLIENT *clnt_com_create(struct sockaddr_in *, u_long, u_long, int *,
+ char *);
+static void pmapdump(int, char **);
+static void get_inet_address(struct sockaddr_in *, char *);
+#endif
+
+static bool_t reply_proc(void *, struct netbuf *, struct netconfig *);
+static void brdcst(int, char **);
+static void addrping(char *, char *, int, char **);
+static void progping(char *, int, char **);
+static CLIENT *clnt_addr_create(char *, struct netconfig *, u_long, u_long);
+static CLIENT *clnt_rpcbind_create(char *, int, struct netbuf **);
+static CLIENT *getclnthandle(char *, struct netconfig *, u_long,
+ struct netbuf **);
+static CLIENT *local_rpcb(u_long, u_long);
+static int pstatus(CLIENT *, u_long, u_long);
+static void rpcbdump(int, char *, int, char **);
+static void rpcbgetstat(int, char **);
+static void rpcbaddrlist(char *, int, char **);
+static void deletereg(char *, int, char **);
+static void print_rmtcallstat(int, rpcb_stat *);
+static void print_getaddrstat(int, rpcb_stat *);
+static void usage(void);
+static u_long getprognum(char *);
+static u_long getvers(char *);
+static char *spaces(int);
+static bool_t add_version(struct rpcbdump_short *, u_long);
+static bool_t add_netid(struct rpcbdump_short *, char *);
+
+int main(int argc, char **argv);
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char **argv)
{
register int c;
int errflg;
int function;
- u_short portnum;
+ char *netid = NULL;
+ char *address = NULL;
+#ifdef PORTMAP
+ char *strptr;
+ u_short portnum = 0;
+#endif
function = NONE;
- portnum = 0;
errflg = 0;
- while ((c = getopt(argc, argv, "ptubdn:")) != -1) {
+#ifdef PORTMAP
+ while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != -1) {
+#else
+ while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != -1) {
+#endif
switch (c) {
-
+#ifdef PORTMAP
case 'p':
if (function != NONE)
errflg = 1;
@@ -121,15 +201,28 @@ main(argc, argv)
function = UDPPING;
break;
- case 'b':
+ case 'n':
+ portnum = (u_short) strtol(optarg, &strptr, 10);
+ if (strptr == optarg || *strptr != '\0') {
+ fprintf(stderr,
+ "rpcinfo: %s is illegal port number\n",
+ optarg);
+ exit(1);
+ }
+ break;
+#endif
+ case 'a':
+ address = optarg;
if (function != NONE)
errflg = 1;
else
- function = BRDCST;
+ function = ADDRPING;
break;
-
- case 'n':
- portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */
+ case 'b':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = BROADCAST;
break;
case 'd':
@@ -139,18 +232,50 @@ main(argc, argv)
function = DELETES;
break;
+ case 'l':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBADDRLIST;
+ break;
+
+ case 'm':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBGETSTAT;
+ break;
+
+ case 's':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBDUMP_SHORT;
+ break;
+
+ case 'T':
+ netid = optarg;
+ break;
case '?':
errflg = 1;
+ break;
}
}
- if (errflg || function == NONE) {
+ if (errflg || ((function == ADDRPING) && !netid)) {
usage();
return (1);
}
- switch (function) {
+ if (function == NONE) {
+ if (argc - optind > 1)
+ function = PROGPING;
+ else
+ function = RPCBDUMP;
+ }
+ switch (function) {
+#ifdef PORTMAP
case PMAPDUMP:
if (portnum != 0) {
usage();
@@ -160,375 +285,270 @@ main(argc, argv)
break;
case UDPPING:
- udpping(portnum, argc - optind, argv + optind);
+ ip_ping(portnum, "udp", argc - optind, argv + optind);
break;
case TCPPING:
- tcpping(portnum, argc - optind, argv + optind);
+ ip_ping(portnum, "tcp", argc - optind, argv + optind);
break;
-
- case BRDCST:
- if (portnum != 0) {
- usage();
- return (1);
- }
+#endif
+ case BROADCAST:
brdcst(argc - optind, argv + optind);
break;
-
case DELETES:
- deletereg(argc - optind, argv + optind);
+ deletereg(netid, argc - optind, argv + optind);
+ break;
+ case ADDRPING:
+ addrping(address, netid, argc - optind, argv + optind);
+ break;
+ case PROGPING:
+ progping(netid, argc - optind, argv + optind);
+ break;
+ case RPCBDUMP:
+ case RPCBDUMP_SHORT:
+ rpcbdump(function, netid, argc - optind, argv + optind);
+ break;
+ case RPCBGETSTAT:
+ rpcbgetstat(argc - optind, argv + optind);
+ break;
+ case RPCBADDRLIST:
+ rpcbaddrlist(netid, argc - optind, argv + optind);
break;
}
-
return (0);
}
-static void
-udpping(portnum, argc, argv)
- u_short portnum;
- int argc;
- char **argv;
+static CLIENT *
+local_rpcb(u_long prog, u_long vers)
{
- struct timeval to;
- struct sockaddr_in addr;
- enum clnt_stat rpc_stat;
- CLIENT *client;
- u_long prognum, vers, minvers, maxvers;
- int sock = RPC_ANYSOCK;
- struct rpc_err rpcerr;
- int failure;
+ struct netbuf nbuf;
+ struct sockaddr_un sun;
+ int sock;
+
+ memset(&sun, 0, sizeof sun);
+ sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ return NULL;
+
+ sun.sun_family = AF_LOCAL;
+ strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+ nbuf.len = sun.sun_len = SUN_LEN(&sun);
+ nbuf.maxlen = sizeof (struct sockaddr_un);
+ nbuf.buf = &sun;
+
+ return clnt_vc_create(sock, &nbuf, prog, vers, 0, 0);
+}
+
+#ifdef PORTMAP
+static CLIENT *
+clnt_com_create(struct sockaddr_in *addr, u_long prog, u_long vers,
+ int *fdp, char *trans)
+{
+ CLIENT *clnt;
+
+ if (strcmp(trans, "tcp") == 0) {
+ clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0);
+ } else {
+ struct timeval to;
- if (argc < 2 || argc > 3) {
- usage();
- exit(1);
- }
- prognum = getprognum(argv[1]);
- get_inet_address(&addr, argv[0]);
- /* Open the socket here so it will survive calls to clnt_destroy */
- sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock < 0) {
- perror("rpcinfo: socket");
- exit(1);
- }
- failure = 0;
- if (argc == 2) {
- /*
- * A call to version 0 should fail with a program/version
- * mismatch, and give us the range of versions supported.
- */
- addr.sin_port = htons(portnum);
to.tv_sec = 5;
to.tv_usec = 0;
- if ((client = clntudp_create(&addr, prognum, (u_long)0,
- to, &sock)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu is not available\n",
- prognum);
- exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
- xdr_void, (char *)NULL, to);
- if (rpc_stat == RPC_PROGVERSMISMATCH) {
- clnt_geterr(client, &rpcerr);
- minvers = rpcerr.re_vers.low;
- maxvers = rpcerr.re_vers.high;
- } else if (rpc_stat == RPC_SUCCESS) {
- /*
- * Oh dear, it DOES support version 0.
- * Let's try version MAX_VERS.
- */
- addr.sin_port = htons(portnum);
- to.tv_sec = 5;
- to.tv_usec = 0;
- if ((client = clntudp_create(&addr, prognum, MAX_VERS,
- to, &sock)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, MAX_VERS);
- exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, NULLPROC, xdr_void,
- (char *)NULL, xdr_void, (char *)NULL, to);
- if (rpc_stat == RPC_PROGVERSMISMATCH) {
- clnt_geterr(client, &rpcerr);
- minvers = rpcerr.re_vers.low;
- maxvers = rpcerr.re_vers.high;
- } else if (rpc_stat == RPC_SUCCESS) {
- /*
- * It also supports version MAX_VERS.
- * Looks like we have a wise guy.
- * OK, we give them information on all
- * 4 billion versions they support...
- */
- minvers = 0;
- maxvers = MAX_VERS;
- } else {
- (void) pstatus(client, prognum, MAX_VERS);
- exit(1);
- }
- } else {
- (void) pstatus(client, prognum, (u_long)0);
- exit(1);
- }
- clnt_destroy(client);
- for (vers = minvers; vers <= maxvers; vers++) {
- addr.sin_port = htons(portnum);
- to.tv_sec = 5;
- to.tv_usec = 0;
- if ((client = clntudp_create(&addr, prognum, vers,
- to, &sock)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, vers);
- exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, NULLPROC, xdr_void,
- (char *)NULL, xdr_void, (char *)NULL, to);
- if (pstatus(client, prognum, vers) < 0)
- failure = 1;
- clnt_destroy(client);
- }
+ clnt = clntudp_create(addr, prog, vers, to, fdp);
}
- else {
- vers = getvers(argv[2]);
- addr.sin_port = htons(portnum);
- to.tv_sec = 5;
- to.tv_usec = 0;
- if ((client = clntudp_create(&addr, prognum, vers,
- to, &sock)) == NULL) {
- clnt_pcreateerror("rpcinfo");
+ if (clnt == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ if (vers == MIN_VERS)
+ printf("program %lu is not available\n", prog);
+ else
printf("program %lu version %lu is not available\n",
- prognum, vers);
- exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
- xdr_void, (char *)NULL, to);
- if (pstatus(client, prognum, vers) < 0)
- failure = 1;
- }
- (void) close(sock); /* Close it up again */
- if (failure)
+ prog, vers);
exit(1);
+ }
+ return (clnt);
}
+/*
+ * If portnum is 0, then go and get the address from portmapper, which happens
+ * transparently through clnt*_create(); If version number is not given, it
+ * tries to find out the version number by making a call to version 0 and if
+ * that fails, it obtains the high order and the low order version number. If
+ * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
+ */
static void
-tcpping(portnum, argc, argv)
- u_short portnum;
- int argc;
- char **argv;
+ip_ping(u_short portnum, char *trans, int argc, char **argv)
{
+ CLIENT *client;
+ int fd = RPC_ANYFD;
struct timeval to;
struct sockaddr_in addr;
enum clnt_stat rpc_stat;
- CLIENT *client;
u_long prognum, vers, minvers, maxvers;
- int sock = RPC_ANYSOCK;
struct rpc_err rpcerr;
- int failure;
+ int failure = 0;
if (argc < 2 || argc > 3) {
usage();
exit(1);
}
+ to.tv_sec = 10;
+ to.tv_usec = 0;
prognum = getprognum(argv[1]);
get_inet_address(&addr, argv[0]);
- failure = 0;
- if (argc == 2) {
+ if (argc == 2) { /* Version number not known */
/*
* A call to version 0 should fail with a program/version
* mismatch, and give us the range of versions supported.
*/
- addr.sin_port = htons(portnum);
- if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
- &sock, 0, 0)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu is not available\n",
- prognum);
+ vers = MIN_VERS;
+ } else {
+ vers = getvers(argv[2]);
+ }
+ addr.sin_port = htons(portnum);
+ client = clnt_com_create(&addr, prognum, vers, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void, (char *)NULL,
+ to);
+ if (argc != 2) {
+ /* Version number was known */
+ if (pstatus(client, prognum, vers) < 0)
exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
- xdr_void, (char *)NULL, to);
+ (void) CLNT_DESTROY(client);
+ return;
+ }
+ /* Version number not known */
+ (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ (void) CLNT_DESTROY(client);
+ addr.sin_port = htons(portnum);
+ client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
if (rpc_stat == RPC_PROGVERSMISMATCH) {
clnt_geterr(client, &rpcerr);
minvers = rpcerr.re_vers.low;
maxvers = rpcerr.re_vers.high;
} else if (rpc_stat == RPC_SUCCESS) {
/*
- * Oh dear, it DOES support version 0.
- * Let's try version MAX_VERS.
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
*/
- addr.sin_port = htons(portnum);
- if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
- &sock, 0, 0)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, MAX_VERS);
- exit(1);
- }
- to.tv_sec = 10;
- to.tv_usec = 0;
- rpc_stat = clnt_call(client, NULLPROC, xdr_void,
- (char *)NULL, xdr_void, (char *)NULL, to);
- if (rpc_stat == RPC_PROGVERSMISMATCH) {
- clnt_geterr(client, &rpcerr);
- minvers = rpcerr.re_vers.low;
- maxvers = rpcerr.re_vers.high;
- } else if (rpc_stat == RPC_SUCCESS) {
- /*
- * It also supports version MAX_VERS.
- * Looks like we have a wise guy.
- * OK, we give them information on all
- * 4 billion versions they support...
- */
- minvers = 0;
- maxvers = MAX_VERS;
- } else {
- (void) pstatus(client, prognum, MAX_VERS);
- exit(1);
- }
+ minvers = 0;
+ maxvers = MAX_VERS;
} else {
- (void) pstatus(client, prognum, MIN_VERS);
+ (void) pstatus(client, prognum, MAX_VERS);
exit(1);
}
- clnt_destroy(client);
- (void) close(sock);
- sock = RPC_ANYSOCK; /* Re-initialize it for later */
- for (vers = minvers; vers <= maxvers; vers++) {
- addr.sin_port = htons(portnum);
- if ((client = clnttcp_create(&addr, prognum, vers,
- &sock, 0, 0)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, vers);
- exit(1);
- }
- to.tv_usec = 0;
- to.tv_sec = 10;
- rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
- xdr_void, (char *)NULL, to);
- if (pstatus(client, prognum, vers) < 0)
- failure = 1;
- clnt_destroy(client);
- (void) close(sock);
- sock = RPC_ANYSOCK;
- }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
}
- else {
- vers = getvers(argv[2]);
+ (void) CLNT_DESTROY(client);
+ for (vers = minvers; vers <= maxvers; vers++) {
addr.sin_port = htons(portnum);
- if ((client = clnttcp_create(&addr, prognum, vers, &sock,
- 0, 0)) == NULL) {
- clnt_pcreateerror("rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, vers);
- exit(1);
- }
- to.tv_usec = 0;
- to.tv_sec = 10;
- rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
- xdr_void, (char *)NULL, to);
+ client = clnt_com_create(&addr, prognum, vers, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
if (pstatus(client, prognum, vers) < 0)
- failure = 1;
+ failure = 1;
+ (void) CLNT_DESTROY(client);
}
if (failure)
exit(1);
+ (void) close(fd);
+ return;
}
/*
- * This routine should take a pointer to an "rpc_err" structure, rather than
- * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
- * a CLIENT structure rather than a pointer to an "rpc_err" structure.
- * As such, we have to keep the CLIENT structure around in order to print
- * a good error message.
+ * Dump all the portmapper registerations
*/
-static int
-pstatus(client, prognum, vers)
- register CLIENT *client;
- u_long prognum;
- u_long vers;
-{
- struct rpc_err rpcerr;
-
- clnt_geterr(client, &rpcerr);
- if (rpcerr.re_status != RPC_SUCCESS) {
- clnt_perror(client, "rpcinfo");
- printf("program %lu version %lu is not available\n",
- prognum, vers);
- return (-1);
- } else {
- printf("program %lu version %lu ready and waiting\n",
- prognum, vers);
- return (0);
- }
-}
-
static void
-pmapdump(argc, argv)
- int argc;
- char **argv;
+pmapdump(int argc, char **argv)
{
struct sockaddr_in server_addr;
- register struct hostent *hp;
struct pmaplist *head = NULL;
int socket = RPC_ANYSOCK;
struct timeval minutetimeout;
register CLIENT *client;
struct rpcent *rpc;
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ char *host;
if (argc > 1) {
usage();
exit(1);
}
- if (argc == 1)
- get_inet_address(&server_addr, argv[0]);
- else {
- bzero((char *)&server_addr, sizeof server_addr);
- server_addr.sin_family = AF_INET;
- if ((hp = gethostbyname("localhost")) != NULL)
- bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
- MIN(hp->h_length,sizeof(server_addr.sin_addr)));
- else
- server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
- }
- minutetimeout.tv_sec = 60;
- minutetimeout.tv_usec = 0;
- server_addr.sin_port = htons(PMAPPORT);
- if ((client = clnttcp_create(&server_addr, PMAPPROG,
- PMAPVERS, &socket, 50, 500)) == NULL) {
+ if (argc == 1) {
+ host = argv[0];
+ get_inet_address(&server_addr, host);
+ server_addr.sin_port = htons(PMAPPORT);
+ client = clnttcp_create(&server_addr, PMAPPROG, PMAPVERS,
+ &socket, 50, 500);
+ } else
+ client = local_rpcb(PMAPPROG, PMAPVERS);
+
+ if (client == NULL) {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR) {
+ /*
+ * "Misc. TLI error" is not too helpful. Most likely
+ * the connection to the remote server timed out, so
+ * this error is at least less perplexing.
+ */
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
clnt_pcreateerror("rpcinfo: can't contact portmapper");
exit(1);
}
- if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
- xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
- fprintf(stderr, "rpcinfo: can't contact portmapper: ");
- clnt_perror(client, "rpcinfo");
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *)&head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ CLNT_GETERR(client, &err);
+ if (err.re_vers.low > PMAPVERS)
+ fprintf(stderr,
+ "%s does not support portmapper. Try rpcinfo %s instead\n",
+ host, host);
+ exit(1);
+ }
+ clnt_perror(client, "rpcinfo: can't contact portmapper");
exit(1);
}
if (head == NULL) {
printf("No remote programs registered.\n");
} else {
- printf(" program vers proto port\n");
+ printf(" program vers proto port service\n");
for (; head != NULL; head = head->pml_next) {
printf("%10ld%5ld",
- head->pml_map.pm_prog,
- head->pml_map.pm_vers);
+ head->pml_map.pm_prog,
+ head->pml_map.pm_vers);
if (head->pml_map.pm_prot == IPPROTO_UDP)
- printf("%6s", "udp");
+ printf("%6s", "udp");
else if (head->pml_map.pm_prot == IPPROTO_TCP)
printf("%6s", "tcp");
+ else if (head->pml_map.pm_prot == IPPROTO_ST)
+ printf("%6s", "unix");
else
- printf("%6ld", head->pml_map.pm_prot);
- printf("%7ld", head->pml_map.pm_port);
+ printf("%6ld", head->pml_map.pm_prot);
+ printf("%7ld", head->pml_map.pm_port);
rpc = getrpcbynumber(head->pml_map.pm_prog);
if (rpc)
printf(" %s\n", rpc->r_name);
@@ -538,6 +558,41 @@ pmapdump(argc, argv)
}
}
+static void
+get_inet_address(struct sockaddr_in *addr, char *host)
+{
+ struct netconfig *nconf;
+ struct addrinfo hints, *res;
+ int error;
+
+ (void) memset((char *)addr, 0, sizeof (*addr));
+ addr->sin_addr.s_addr = inet_addr(host);
+ if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
+ if ((nconf = __rpc_getconfip("udp")) == NULL &&
+ (nconf = __rpc_getconfip("tcp")) == NULL) {
+ fprintf(stderr,
+ "rpcinfo: couldn't find a suitable transport\n");
+ exit(1);
+ } else {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET;
+ if ((error = getaddrinfo(host, "rpcbind", &hints, &res))
+ != 0) {
+ fprintf(stderr, "rpcinfo: %s: %s\n",
+ host, gai_strerror(error));
+ exit(1);
+ } else {
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ }
+ (void) freenetconfigent(nconf);
+ }
+ } else {
+ addr->sin_family = AF_INET;
+ }
+}
+#endif /* PORTMAP */
+
/*
* reply_proc collects replies from the broadcast.
* to get a unique list of responses the output of rpcinfo should
@@ -546,23 +601,32 @@ pmapdump(argc, argv)
/*ARGSUSED*/
static bool_t
-reply_proc(res, who)
- void *res; /* Nothing comes back */
- struct sockaddr_in *who; /* Who sent us the reply */
+reply_proc(void *res, struct netbuf *who, struct netconfig *nconf)
+ /* void *res; Nothing comes back */
+ /* struct netbuf *who; Who sent us the reply */
+ /* struct netconfig *nconf; On which transport the reply came */
{
- register struct hostent *hp;
+ char *uaddr;
+ char hostbuf[NI_MAXHOST];
+ char *hostname;
+ struct sockaddr *sa = (struct sockaddr *)who->buf;
- hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
- AF_INET);
- printf("%s %s\n", inet_ntoa(who->sin_addr),
- (hp == NULL) ? "(unknown)" : hp->h_name);
- return(FALSE);
+ if (getnameinfo(sa, sa->sa_len, hostbuf, NI_MAXHOST, NULL, 0, 0)) {
+ hostname = UNKNOWN;
+ } else {
+ hostname = hostbuf;
+ }
+ if (!(uaddr = taddr2uaddr(nconf, who))) {
+ uaddr = UNKNOWN;
+ }
+ printf("%s\t%s\n", uaddr, hostname);
+ if (strcmp(uaddr, UNKNOWN))
+ free((char *)uaddr);
+ return (FALSE);
}
static void
-brdcst(argc, argv)
- int argc;
- char **argv;
+brdcst(int argc, char **argv)
{
enum clnt_stat rpc_stat;
u_long prognum, vers;
@@ -573,89 +637,1079 @@ brdcst(argc, argv)
}
prognum = getprognum(argv[0]);
vers = getvers(argv[1]);
- rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
- (char *)NULL, xdr_void, (char *)NULL, reply_proc);
+ rpc_stat = rpc_broadcast(prognum, vers, NULLPROC,
+ (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, (resultproc_t) reply_proc, NULL);
if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
- clnt_sperrno(rpc_stat));
+ clnt_sperrno(rpc_stat));
exit(1);
}
exit(0);
}
+static bool_t
+add_version(struct rpcbdump_short *rs, u_long vers)
+{
+ struct verslist *vl;
+
+ for (vl = rs->vlist; vl; vl = vl->next)
+ if (vl->vers == vers)
+ break;
+ if (vl)
+ return (TRUE);
+ vl = (struct verslist *)malloc(sizeof (struct verslist));
+ if (vl == NULL)
+ return (FALSE);
+ vl->vers = vers;
+ vl->next = rs->vlist;
+ rs->vlist = vl;
+ return (TRUE);
+}
+
+static bool_t
+add_netid(struct rpcbdump_short *rs, char *netid)
+{
+ struct netidlist *nl;
+
+ for (nl = rs->nlist; nl; nl = nl->next)
+ if (strcmp(nl->netid, netid) == 0)
+ break;
+ if (nl)
+ return (TRUE);
+ nl = (struct netidlist *)malloc(sizeof (struct netidlist));
+ if (nl == NULL)
+ return (FALSE);
+ nl->netid = netid;
+ nl->next = rs->nlist;
+ rs->nlist = nl;
+ return (TRUE);
+}
+
static void
-deletereg(argc, argv)
- int argc;
- char **argv;
-{ u_long prog_num, version_num ;
+rpcbdump(int dumptype, char *netid, int argc, char **argv)
+{
+ rpcblist_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ struct netidlist *nl;
+ struct verslist *vl;
+ struct rpcbdump_short *rs, *rs_tail;
+ char buf[256];
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ struct rpcbdump_short *rs_head = NULL;
+
+ if (argc > 1) {
+ usage();
+ exit(1);
+ }
+ if (argc == 1) {
+ host = argv[0];
+ if (netid == NULL) {
+ client = clnt_rpcbind_create(host, RPCBVERS, NULL);
+ } else {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ nc_perror("rpcinfo: invalid transport");
+ exit(1);
+ }
+ client = getclnthandle(host, nconf, RPCBVERS, NULL);
+ if (nconf)
+ (void) freenetconfigent(nconf);
+ }
+ } else
+ client = local_rpcb(PMAPPROG, RPCBVERS);
+
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ int vers;
+
+ CLNT_GETERR(client, &err);
+ if (err.re_vers.low == RPCBVERS4) {
+ vers = RPCBVERS4;
+ clnt_control(client, CLSET_VERS, (char *)&vers);
+ clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ } else {
+ if (err.re_vers.high == PMAPVERS) {
+ int high, low;
+ struct pmaplist *pmaphead = NULL;
+ rpcblist_ptr list, prev;
+
+ vers = PMAPVERS;
+ clnt_control(client, CLSET_VERS, (char *)&vers);
+ clnt_st = CLNT_CALL(client, PMAPPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_pmaplist_ptr,
+ (char *)&pmaphead, minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ /*
+ * convert to rpcblist_ptr format
+ */
+ for (head = NULL; pmaphead != NULL;
+ pmaphead = pmaphead->pml_next) {
+ list = (rpcblist *)malloc(sizeof (rpcblist));
+ if (list == NULL)
+ goto error;
+ if (head == NULL)
+ head = list;
+ else
+ prev->rpcb_next = (rpcblist_ptr) list;
+
+ list->rpcb_next = NULL;
+ list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
+ list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
+ if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
+ list->rpcb_map.r_netid = "udp";
+ else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
+ list->rpcb_map.r_netid = "tcp";
+ else {
+#define MAXLONG_AS_STRING "2147483648"
+ list->rpcb_map.r_netid =
+ malloc(strlen(MAXLONG_AS_STRING) + 1);
+ if (list->rpcb_map.r_netid == NULL)
+ goto error;
+ sprintf(list->rpcb_map.r_netid, "%6ld",
+ pmaphead->pml_map.pm_prot);
+ }
+ list->rpcb_map.r_owner = UNKNOWN;
+ low = pmaphead->pml_map.pm_port & 0xff;
+ high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
+ list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX");
+ sprintf(&list->rpcb_map.r_addr[8], "%d.%d",
+ high, low);
+ prev = list;
+ }
+ }
+ }
+ } else { /* any other error */
+failed:
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ }
+ if (head == NULL) {
+ printf("No remote programs registered.\n");
+ } else if (dumptype == RPCBDUMP) {
+ printf(
+" program version netid address service owner\n");
+ for (; head != NULL; head = head->rpcb_next) {
+ printf("%10u%5u ",
+ head->rpcb_map.r_prog, head->rpcb_map.r_vers);
+ printf("%-9s ", head->rpcb_map.r_netid);
+ printf("%-22s", head->rpcb_map.r_addr);
+ rpc = getrpcbynumber(head->rpcb_map.r_prog);
+ if (rpc)
+ printf(" %-10s", rpc->r_name);
+ else
+ printf(" %-10s", "-");
+ printf(" %s\n", head->rpcb_map.r_owner);
+ }
+ } else if (dumptype == RPCBDUMP_SHORT) {
+ for (; head != NULL; head = head->rpcb_next) {
+ for (rs = rs_head; rs; rs = rs->next)
+ if (head->rpcb_map.r_prog == rs->prog)
+ break;
+ if (rs == NULL) {
+ rs = (struct rpcbdump_short *)
+ malloc(sizeof (struct rpcbdump_short));
+ if (rs == NULL)
+ goto error;
+ rs->next = NULL;
+ if (rs_head == NULL) {
+ rs_head = rs;
+ rs_tail = rs;
+ } else {
+ rs_tail->next = rs;
+ rs_tail = rs;
+ }
+ rs->prog = head->rpcb_map.r_prog;
+ rs->owner = head->rpcb_map.r_owner;
+ rs->nlist = NULL;
+ rs->vlist = NULL;
+ }
+ if (add_version(rs, head->rpcb_map.r_vers) == FALSE)
+ goto error;
+ if (add_netid(rs, head->rpcb_map.r_netid) == FALSE)
+ goto error;
+ }
+ printf(
+" program version(s) netid(s) service owner\n");
+ for (rs = rs_head; rs; rs = rs->next) {
+ char *p = buf;
+
+ printf("%10ld ", rs->prog);
+ for (vl = rs->vlist; vl; vl = vl->next) {
+ sprintf(p, "%d", vl->vers);
+ p = p + strlen(p);
+ if (vl->next)
+ sprintf(p++, ",");
+ }
+ printf("%-10s", buf);
+ buf[0] = NULL;
+ for (nl = rs->nlist; nl; nl = nl->next) {
+ strcat(buf, nl->netid);
+ if (nl->next)
+ strcat(buf, ",");
+ }
+ printf("%-32s", buf);
+ rpc = getrpcbynumber(rs->prog);
+ if (rpc)
+ printf(" %-11s", rpc->r_name);
+ else
+ printf(" %-11s", "-");
+ printf(" %s\n", rs->owner);
+ }
+ }
+ clnt_destroy(client);
+ return;
+error: fprintf(stderr, "rpcinfo: no memory\n");
+ return;
+}
+
+static char nullstring[] = "\000";
+
+static void
+rpcbaddrlist(char *netid, int argc, char **argv)
+{
+ rpcb_entry_list_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ RPCB parms;
+ struct netbuf *targaddr;
+
+ if (argc != 3) {
+ usage();
+ exit(1);
+ }
+ host = argv[0];
+ if (netid == NULL) {
+ client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
+ } else {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ nc_perror("rpcinfo: invalid transport");
+ exit(1);
+ }
+ client = getclnthandle(host, nconf, RPCBVERS4, &targaddr);
+ if (nconf)
+ (void) freenetconfigent(nconf);
+ }
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ parms.r_prog = getprognum(argv[1]);
+ parms.r_vers = getvers(argv[2]);
+ parms.r_netid = client->cl_netid;
+ if (targaddr == NULL) {
+ parms.r_addr = nullstring; /* for XDRing */
+ } else {
+ /*
+ * We also send the remote system the address we
+ * used to contact it in case it can help it
+ * connect back with us
+ */
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(client->cl_netid);
+ if (nconf != NULL) {
+ parms.r_addr = taddr2uaddr(nconf, targaddr);
+ if (parms.r_addr == NULL)
+ parms.r_addr = nullstring;
+ freenetconfigent(nconf);
+ } else {
+ parms.r_addr = nullstring; /* for XDRing */
+ }
+ free(targaddr->buf);
+ free(targaddr);
+ }
+ parms.r_owner = nullstring;
+
+ if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb,
+ (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *) &head, minutetimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ if (head == NULL) {
+ printf("No remote programs registered.\n");
+ } else {
+ printf(
+ " program vers tp_family/name/class address\t\t service\n");
+ for (; head != NULL; head = head->rpcb_entry_next) {
+ rpcb_entry *re;
+ char buf[128];
+
+ re = &head->rpcb_entry_map;
+ printf("%10u%3u ",
+ parms.r_prog, parms.r_vers);
+ sprintf(buf, "%s/%s/%s ",
+ re->r_nc_protofmly, re->r_nc_proto,
+ re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
+ re->r_nc_semantics == NC_TPI_COTS ? "cots" :
+ "cots_ord");
+ printf("%-24s", buf);
+ printf("%-24s", re->r_maddr);
+ rpc = getrpcbynumber(parms.r_prog);
+ if (rpc)
+ printf(" %-13s", rpc->r_name);
+ else
+ printf(" %-13s", "-");
+ printf("\n");
+ }
+ }
+ clnt_destroy(client);
+ return;
+}
+
+/*
+ * monitor rpcbind
+ */
+static void
+rpcbgetstat(int argc, char **argv)
+{
+ rpcb_stat_byvers inf;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ char *host;
+ int i, j;
+ rpcbs_addrlist *pa;
+ rpcbs_rmtcalllist *pr;
+ int cnt, flen;
+#define MAXFIELD 64
+ char fieldbuf[MAXFIELD];
+#define MAXLINE 256
+ char linebuf[MAXLINE];
+ char *cp, *lp;
+ char *pmaphdr[] = {
+ "NULL", "SET", "UNSET", "GETPORT",
+ "DUMP", "CALLIT"
+ };
+ char *rpcb3hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U"
+ };
+ char *rpcb4hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
+ };
+
+#define TABSTOP 8
+
+ if (argc >= 1) {
+ host = argv[0];
+ client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
+ } else
+ client = local_rpcb(PMAPPROG, RPCBVERS4);
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ memset((char *)&inf, 0, sizeof (rpcb_stat_byvers));
+ if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout)
+ != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ printf("PORTMAP (version 2) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_2; i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case PMAPPROC_SET:
+ sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
+ break;
+ case PMAPPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_2_STAT].unsetinfo);
+ break;
+ case PMAPPROC_GETPORT:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case PMAPPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", pmaphdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(pmaphdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) {
+ printf("PMAP_RMTCALL call statistics\n");
+ print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf("\n");
+ }
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) {
+ printf("PMAP_GETPORT call statistics\n");
+ print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf("\n");
+ }
+
+ printf("RPCBIND (version 3) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_3; i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case RPCBPROC_SET:
+ sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_3_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", rpcb3hdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(rpcb3hdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) {
+ printf("RPCB_RMTCALL (version 3) call statistics\n");
+ print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf("\n");
+ }
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) {
+ printf("RPCB_GETADDR (version 3) call statistics\n");
+ print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf("\n");
+ }
+
+ printf("RPCBIND (version 4) statistics\n");
+
+ for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */
+ lp = linebuf;
+ for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case RPCBPROC_SET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_4_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_4_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ /*
+ * XXX: We also add RPCBPROC_GETADDRLIST queries to
+ * RPCB_GETADDR because rpcbind includes the
+ * RPCB_GETADDRLIST successes in RPCB_GETADDR.
+ */
+ if (i != RPCBPROC_GETADDR)
+ sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
+ else
+ sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", rpcb4hdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(rpcb4hdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n", linebuf);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) {
+ printf("\n");
+ printf("RPCB_RMTCALL (version 4) call statistics\n");
+ print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) {
+ printf("\n");
+ printf("RPCB_GETADDR (version 4) call statistics\n");
+ print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+ clnt_destroy(client);
+}
+
+/*
+ * Delete registeration for this (prog, vers, netid)
+ */
+static void
+deletereg(char *netid, int argc, char **argv)
+{
+ struct netconfig *nconf = NULL;
if (argc != 2) {
- usage() ;
- exit(1) ;
- }
- if (getuid()) /* This command allowed only to root */
- errx(1, "sorry, you are not root") ;
- prog_num = getprognum(argv[0]);
- version_num = getvers(argv[1]);
- if ((pmap_unset(prog_num, version_num)) == 0)
- errx(1, "could not delete registration for prog %s version %s",
- argv[0], argv[1]) ;
+ usage();
+ exit(1);
+ }
+ if (netid) {
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ fprintf(stderr, "rpcinfo: netid %s not supported\n",
+ netid);
+ exit(1);
+ }
+ }
+ if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) {
+ fprintf(stderr,
+ "rpcinfo: Could not delete registration for prog %s version %s\n",
+ argv[0], argv[1]);
+ exit(1);
+ }
+}
+
+/*
+ * Create and return a handle for the given nconf.
+ * Exit if cannot create handle.
+ */
+static CLIENT *
+clnt_addr_create(char *address, struct netconfig *nconf,
+ u_long prog, u_long vers)
+{
+ CLIENT *client;
+ static struct netbuf *nbuf;
+ static int fd = RPC_ANYFD;
+
+ if (fd == RPC_ANYFD) {
+ if ((fd = __rpc_nconf2fd(nconf)) == -1) {
+ rpc_createerr.cf_stat = RPC_TLIERROR;
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ /* Convert the uaddr to taddr */
+ nbuf = uaddr2taddr(nconf, address);
+ if (nbuf == NULL) {
+ errx(1, "rpcinfo: no address for client handle");
+ exit(1);
+ }
+ }
+ client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0);
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ return (client);
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is not contacted for this service. The requests are
+ * sent directly to the services themselves.
+ */
+static void
+addrping(char *address, char *netid, int argc, char **argv)
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_long prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+ int fd;
+
+ if (argc < 1 || argc > 2 || (netid == NULL)) {
+ usage();
+ exit(1);
+ }
+ nconf = getnetconfigent(netid);
+ if (nconf == (struct netconfig *)NULL) {
+ fprintf(stderr, "rpcinfo: Could not find %s\n", netid);
+ exit(1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ prognum = getprognum(argv[0]);
+ if (argc == 1) { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ } else {
+ versnum = getvers(argv[1]);
+ }
+ client = clnt_addr_create(address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (argc == 2) {
+ /* Version number was known */
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
+ }
+ /* Version number not known */
+ (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
+ (void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ (void) CLNT_DESTROY(client);
+ client = clnt_addr_create(address, nconf, prognum, MAX_VERS);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ } else {
+ (void) pstatus(client, prognum, MAX_VERS);
+ exit(1);
+ }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
+ }
+ (void) CLNT_DESTROY(client);
+ for (versnum = minvers; versnum <= maxvers; versnum++) {
+ client = clnt_addr_create(address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ }
+ (void) close(fd);
+ if (failure)
+ exit(1);
+ return;
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is *contacted* for this service. The requests are
+ * then sent directly to the services themselves.
+ */
+static void
+progping(char *netid, int argc, char **argv)
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_long prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+
+ if (argc < 2 || argc > 3 || (netid == NULL)) {
+ usage();
+ exit(1);
+ }
+ prognum = getprognum(argv[1]);
+ if (argc == 2) { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ } else {
+ versnum = getvers(argv[2]);
+ }
+ if (netid) {
+ nconf = getnetconfigent(netid);
+ if (nconf == (struct netconfig *)NULL) {
+ fprintf(stderr, "rpcinfo: Could not find %s\n", netid);
+ exit(1);
+ }
+ client = clnt_tp_create(argv[0], prognum, versnum, nconf);
+ } else {
+ client = clnt_create(argv[0], prognum, versnum, "NETPATH");
+ }
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (argc == 3) {
+ /* Version number was known */
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
+ }
+ /* Version number not known */
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ versnum = MAX_VERS;
+ (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC,
+ (xdrproc_t) xdr_void, (char *)NULL,
+ (xdrproc_t) xdr_void, (char *)NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ } else {
+ (void) pstatus(client, prognum, MAX_VERS);
+ exit(1);
+ }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
+ }
+ for (versnum = minvers; versnum <= maxvers; versnum++) {
+ (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ }
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
}
static void
usage()
{
- fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
- "usage: rpcinfo [-n portnum] -u host prognum [versnum]",
- " rpcinfo [-n portnum] -t host prognum [versnum]",
- " rpcinfo -p [host]",
- " rpcinfo -b prognum versnum",
- " rpcinfo -d prognum versnum");
+ fprintf(stderr, "Usage: rpcinfo [-m | -s] [host]\n");
+#ifdef PORTMAP
+ fprintf(stderr, " rpcinfo -p [host]\n");
+#endif
+ fprintf(stderr, " rpcinfo -T netid host prognum [versnum]\n");
+ fprintf(stderr, " rpcinfo -l host prognum versnum\n");
+#ifdef PORTMAP
+ fprintf(stderr,
+" rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
+#endif
+ fprintf(stderr,
+" rpcinfo -a serv_address -T netid prognum [version]\n");
+ fprintf(stderr, " rpcinfo -b prognum versnum\n");
+ fprintf(stderr, " rpcinfo -d [-T netid] prognum versnum\n");
}
static u_long
-getprognum(arg)
- char *arg;
+getprognum (char *arg)
{
+ char *strptr;
register struct rpcent *rpc;
register u_long prognum;
+ char *tptr = arg;
- if (isalpha(*arg)) {
+ while (*tptr && isdigit(*tptr++));
+ if (*tptr || isalpha(*(tptr - 1))) {
rpc = getrpcbyname(arg);
- if (rpc == NULL)
- errx(1, "%s is unknown service", arg);
+ if (rpc == NULL) {
+ fprintf(stderr, "rpcinfo: %s is unknown service\n",
+ arg);
+ exit(1);
+ }
prognum = rpc->r_number;
} else {
- prognum = (u_long) atoi(arg);
+ prognum = strtol(arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0') {
+ fprintf(stderr,
+ "rpcinfo: %s is illegal program number\n", arg);
+ exit(1);
+ }
}
-
return (prognum);
}
static u_long
-getvers(arg)
- char *arg;
+getvers(char *arg)
{
+ char *strptr;
register u_long vers;
- vers = (int) atoi(arg);
+ vers = (int) strtol(arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0') {
+ fprintf(stderr, "rpcinfo: %s is illegal version number\n",
+ arg);
+ exit(1);
+ }
return (vers);
}
+/*
+ * This routine should take a pointer to an "rpc_err" structure, rather than
+ * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
+ * a CLIENT structure rather than a pointer to an "rpc_err" structure.
+ * As such, we have to keep the CLIENT structure around in order to print
+ * a good error message.
+ */
+static int
+pstatus(register CLIENT *client, u_long prog, u_long vers)
+{
+ struct rpc_err rpcerr;
+
+ clnt_geterr(client, &rpcerr);
+ if (rpcerr.re_status != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo");
+ printf("program %lu version %lu is not available\n",
+ prog, vers);
+ return (-1);
+ } else {
+ printf("program %lu version %lu ready and waiting\n",
+ prog, vers);
+ return (0);
+ }
+}
+
+static CLIENT *
+clnt_rpcbind_create(char *host, int rpcbversnum, struct netbuf **targaddr)
+{
+ static char *tlist[3] = {
+ "circuit_n", "circuit_v", "datagram_v"
+ };
+ int i;
+ struct netconfig *nconf;
+ CLIENT *clnt = NULL;
+ void *handle;
+
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ for (i = 0; i < 3; i++) {
+ if ((handle = __rpc_setconf(tlist[i])) == NULL)
+ continue;
+ while (clnt == (CLIENT *)NULL) {
+ if ((nconf = __rpc_getconf(handle)) == NULL) {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+ clnt = getclnthandle(host, nconf, rpcbversnum,
+ targaddr);
+ }
+ if (clnt)
+ break;
+ __rpc_endconf(handle);
+ }
+ return (clnt);
+}
+
+static CLIENT*
+getclnthandle(char *host, struct netconfig *nconf,
+ u_long rpcbversnum, struct netbuf **targaddr)
+{
+ struct netbuf addr;
+ struct addrinfo hints, *res;
+ CLIENT *client = NULL;
+
+ /* Get the address of the rpcbind */
+ memset(&hints, 0, sizeof hints);
+ if (getaddrinfo(host, "rpcbind", &hints, &res) != 0) {
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ return (NULL);
+ }
+ addr.len = addr.maxlen = res->ai_addrlen;
+ addr.buf = res->ai_addr;
+ client = clnt_tli_create(RPC_ANYFD, nconf, &addr, RPCBPROG,
+ rpcbversnum, 0, 0);
+ if (client) {
+ if (targaddr != NULL) {
+ *targaddr =
+ (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (*targaddr != NULL) {
+ (*targaddr)->maxlen = addr.maxlen;
+ (*targaddr)->len = addr.len;
+ (*targaddr)->buf = (char *)malloc(addr.len);
+ if ((*targaddr)->buf != NULL) {
+ memcpy((*targaddr)->buf, addr.buf,
+ addr.len);
+ }
+ }
+ }
+ } else {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR) {
+ /*
+ * Assume that the other system is dead; this is a
+ * better error to display to the user.
+ */
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
+ }
+ freeaddrinfo(res);
+ return (client);
+}
+
static void
-get_inet_address(addr, host)
- struct sockaddr_in *addr;
- char *host;
+print_rmtcallstat(int rtype, rpcb_stat *infp)
{
- register struct hostent *hp;
+ register rpcbs_rmtcalllist_ptr pr;
+ struct rpcent *rpc;
- bzero((char *)addr, sizeof *addr);
- addr->sin_addr.s_addr = (u_long) inet_addr(host);
- if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
- if ((hp = gethostbyname(host)) == NULL)
- errx(1, "%s is unknown host\n", host);
- bcopy(hp->h_addr, (char *)&addr->sin_addr,
- MIN(hp->h_length,sizeof(addr->sin_addr)));
+ if (rtype == RPCBVERS_4_STAT)
+ printf(
+ "prog\t\tvers\tproc\tnetid\tindirect success failure\n");
+ else
+ printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
+ for (pr = infp->rmtinfo; pr; pr = pr->next) {
+ rpc = getrpcbynumber(pr->prog);
+ if (rpc)
+ printf("%-16s", rpc->r_name);
+ else
+ printf("%-16d", pr->prog);
+ printf("%d\t%d\t%s\t",
+ pr->vers, pr->proc, pr->netid);
+ if (rtype == RPCBVERS_4_STAT)
+ printf("%d\t ", pr->indirect);
+ printf("%d\t%d\n", pr->success, pr->failure);
+ }
+}
+
+static void
+print_getaddrstat(int rtype, rpcb_stat *infp)
+{
+ rpcbs_addrlist_ptr al;
+ register struct rpcent *rpc;
+
+ printf("prog\t\tvers\tnetid\t success\tfailure\n");
+ for (al = infp->addrinfo; al; al = al->next) {
+ rpc = getrpcbynumber(al->prog);
+ if (rpc)
+ printf("%-16s", rpc->r_name);
+ else
+ printf("%-16d", al->prog);
+ printf("%d\t%s\t %-12d\t%d\n",
+ al->vers, al->netid,
+ al->success, al->failure);
+ }
+}
+
+static char *
+spaces(int howmany)
+{
+ static char space_array[] = /* 64 spaces */
+ " ";
+
+ if (howmany <= 0 || howmany > sizeof (space_array)) {
+ return ("");
}
- addr->sin_family = AF_INET;
+ return (&space_array[sizeof (space_array) - howmany - 1]);
}
diff --git a/usr.bin/rup/rup.c b/usr.bin/rup/rup.c
index aeadfc56ef17..6d414b059be8 100644
--- a/usr.bin/rup/rup.c
+++ b/usr.bin/rup/rup.c
@@ -85,7 +85,7 @@ void remember_host(struct in_addr addr)
}
int
-rstat_reply(char *replyp, struct sockaddr_in *raddrp)
+rstat_reply(caddr_t replyp, struct sockaddr_in *raddrp)
{
struct tm *tmp_time;
struct tm host_time;
@@ -180,7 +180,7 @@ onehost(char *host)
}
addr.sin_addr.s_addr = *(int *)hp->h_addr;
- rstat_reply((char *)&host_stat, &addr);
+ rstat_reply((caddr_t)&host_stat, &addr);
return (0);
}
diff --git a/usr.bin/rusers/rusers.c b/usr.bin/rusers/rusers.c
index a59abd62872d..9b83cb7e3b55 100644
--- a/usr.bin/rusers/rusers.c
+++ b/usr.bin/rusers/rusers.c
@@ -90,7 +90,7 @@ remember_host(struct in_addr addr)
}
int
-rusers_reply(char *replyp, struct sockaddr_in *raddrp)
+rusers_reply(caddr_t replyp, struct sockaddr_in *raddrp)
{
int x, idle;
char date[32], idle_time[64], remote[64];
@@ -192,7 +192,7 @@ onehost(char *host)
if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
errx(1, "%s", clnt_sperror(rusers_clnt, ""));
addr.sin_addr.s_addr = *(int *)hp->h_addr;
- rusers_reply((char *)&up, &addr);
+ rusers_reply((caddr_t)&up, &addr);
}
void
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index c51b87aa035d..7a41e40b0713 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -66,7 +66,6 @@ SUBDIR= IPXrouted \
pim6sd \
pkg_install \
pnpinfo \
- portmap \
ppp \
pppctl \
pppd \
@@ -84,6 +83,7 @@ SUBDIR= IPXrouted \
rip6query \
rmt \
route6d \
+ rpcbind \
rpc.lockd \
rpc.statd \
rpc.umntall \
diff --git a/usr.sbin/bootparamd/callbootd/callbootd.c b/usr.sbin/bootparamd/callbootd/callbootd.c
index 7a09168ac3a9..b7827ac5b95a 100644
--- a/usr.sbin/bootparamd/callbootd/callbootd.c
+++ b/usr.sbin/bootparamd/callbootd/callbootd.c
@@ -118,8 +118,9 @@ char **argv;
} else {
clnt_stat=clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS,
BOOTPARAMPROC_WHOAMI,
- xdr_bp_whoami_arg, &whoami_arg,
- xdr_bp_whoami_res, &stat_whoami_res, eachres_whoami);
+ (xdrproc_t)xdr_bp_whoami_arg, (char *)&whoami_arg,
+ xdr_bp_whoami_res, (char *)&stat_whoami_res,
+ (resultproc_t)eachres_whoami);
exit(0);
}
@@ -138,8 +139,9 @@ char **argv;
} else {
clnt_stat=clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS,
BOOTPARAMPROC_GETFILE,
- xdr_bp_getfile_arg, &getfile_arg,
- xdr_bp_getfile_res, &stat_getfile_res,eachres_getfile);
+ xdr_bp_getfile_arg, (char *)&getfile_arg,
+ xdr_bp_getfile_res, (char *)&stat_getfile_res,
+ (resultproc_t)eachres_getfile);
exit(0);
}
diff --git a/usr.sbin/keyserv/keyserv.c b/usr.sbin/keyserv/keyserv.c
index 72a334af1d05..9a156d51f1be 100644
--- a/usr.sbin/keyserv/keyserv.c
+++ b/usr.sbin/keyserv/keyserv.c
@@ -56,7 +56,6 @@ static const char rcsid[] =
#include <sys/stat.h>
#include <sys/types.h>
#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
#include <sys/param.h>
#include <sys/file.h>
#include <rpc/des_crypt.h>
@@ -162,46 +161,24 @@ main(argc, argv)
setmodulus(HEXMODULUS);
getrootkey(&masterkey, nflag);
-
- /* Create services. */
-
- (void) pmap_unset(KEY_PROG, KEY_VERS);
- (void) pmap_unset(KEY_PROG, KEY_VERS2);
- unlink(KEYSERVSOCK);
-
- transp = svcudp_create(RPC_ANYSOCK);
- if (transp == NULL)
- errx(1, "cannot create udp service");
- if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_UDP))
- errx(1, "unable to register (KEY_PROG, KEY_VERS, udp)");
- if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_UDP))
- errx(1, "unable to register (KEY_PROG, KEY_VERS2, udp)");
-
- transp = svctcp_create(RPC_ANYSOCK, 0, 0);
- if (transp == NULL)
- errx(1, "cannot create tcp service");
- if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_TCP))
- errx(1, "unable to register (KEY_PROG, KEY_VERS, tcp)");
- if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_TCP))
- errx(1, "unable to register (KEY_PROG, KEY_VERS2, tcp)");
-
- transp = svcunix_create(sock, 0, 0, KEYSERVSOCK);
- chmod(KEYSERVSOCK, 0666);
- if (transp == NULL)
- errx(1, "cannot create AF_UNIX service");
- if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, 0))
- errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
- if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, 0))
- errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
- if (!svc_register(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, 0))
- errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");
+ if (svc_create(keyprogram, KEY_PROG, KEY_VERS,
+ "netpath") == 0) {
+ (void) fprintf(stderr,
+ "%s: unable to create service\n", argv[0]);
+ exit(1);
+ }
+
+ if (svc_create(keyprogram, KEY_PROG, KEY_VERS2,
+ "netpath") == 0) {
+ (void) fprintf(stderr,
+ "%s: unable to create service\n", argv[0]);
+ exit(1);
+ }
if (!debugging) {
daemon(0,0);
}
- signal(SIGPIPE, SIG_IGN);
-
svc_run();
abort();
/* NOTREACHED */
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index 2f46a9f2ca9c..b5277656ac1e 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -50,12 +50,15 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpcsvc/mount.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
@@ -83,6 +86,10 @@ static const char rcsid[] =
#include <stdarg.h>
#endif
+#ifndef MOUNTDLOCK
+#define MOUNTDLOCK "/var/run/mountd.lock"
+#endif
+
/*
* Structures for keeping the mount list and export list
*/
@@ -117,13 +124,13 @@ struct exportlist {
#define EX_LINKED 0x1
struct netmsk {
- u_int32_t nt_net;
+ struct sockaddr_storage nt_net;
u_int32_t nt_mask;
char *nt_name;
};
union grouptypes {
- struct hostent *gt_hostent;
+ struct addrinfo *gt_addrinfo;
struct netmsk gt_net;
};
@@ -157,8 +164,8 @@ void add_dlist __P((struct dirlist **, struct dirlist *,
void add_mlist __P((char *, char *));
int check_dirpath __P((char *));
int check_options __P((struct dirlist *));
-int chk_host __P((struct dirlist *, u_int32_t, int *, int *));
-void del_mlist __P((char *, char *));
+int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *));
+int del_mlist __P((char *, char *, struct sockaddr *));
struct dirlist *dirp_search __P((struct dirlist *, char *));
int do_mount __P((struct exportlist *, struct grouplist *, int,
struct xucred *, char *, int, struct statfs *));
@@ -186,18 +193,25 @@ void nextfield __P((char **, char **));
void out_of_mem __P((void));
void parsecred __P((char *, struct xucred *));
int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *));
-int scan_tree __P((struct dirlist *, u_int32_t));
+int scan_tree __P((struct dirlist *, struct sockaddr *));
static void usage __P((void));
int xdr_dir __P((XDR *, char *));
int xdr_explist __P((XDR *, caddr_t));
int xdr_fhs __P((XDR *, caddr_t));
int xdr_mlist __P((XDR *, caddr_t));
+void terminate __P((int));
/* C library */
int getnetgrent();
void endnetgrent();
void setnetgrent();
+static int bitcmp __P((void *, void *, int));
+static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int));
+static int sacmp __P((struct sockaddr *, struct sockaddr *));
+static int allones __P((struct sockaddr_storage *, int));
+static int countones __P((struct sockaddr *));
+
struct exportlist *exphead;
struct mountlist *mlhead;
struct grouplist *grphead;
@@ -213,7 +227,16 @@ int force_v2 = 0;
int resvport_only = 1;
int dir_only = 1;
int log = 0;
+
int opt_flags;
+static int have_v6 = 1;
+#ifdef NI_WITHSCOPEID
+static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID;
+#else
+static const int ninumeric = NI_NUMERICHOST;
+#endif
+
+int mountdlockfd;
/* Bits for above */
#define OP_MAPROOT 0x01
#define OP_MAPALL 0x02
@@ -221,6 +244,7 @@ int opt_flags;
#define OP_MASK 0x08
#define OP_NET 0x10
#define OP_ALLDIRS 0x40
+#define OP_MASKLEN 0x200
#ifdef DEBUG
int debug = 1;
@@ -242,10 +266,26 @@ main(argc, argv)
int argc;
char **argv;
{
- SVCXPRT *udptransp, *tcptransp;
+ SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp;
+ struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf;
+ int udpsock, tcpsock, udp6sock, tcp6sock;
+ int xcreated = 0, s;
+ int one = 1;
int c, error, mib[3];
struct vfsconf vfc;
+ /* Check that another mountd isn't already running. */
+
+ if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1)
+ err(1, "%s", MOUNTDLOCK);
+
+ if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
+ errx(1, "another rpc.mountd is already running. Aborting");
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0)
+ have_v6 = 0;
+ else
+ close(s);
error = getvfsbyname("nfs", &vfc);
if (error && vfsisloadable("nfs")) {
if(vfsload("nfs"))
@@ -301,12 +341,38 @@ main(argc, argv)
signal(SIGQUIT, SIG_IGN);
}
signal(SIGHUP, (void (*) __P((int))) get_exportlist);
+ signal(SIGTERM, terminate);
{ FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");
if (pidfile != NULL) {
fprintf(pidfile, "%d\n", getpid());
fclose(pidfile);
}
}
+ rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL);
+ rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL);
+ udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ /*
+ * We're doing host-based access checks here, so don't allow
+ * v4-in-v6 to confuse things. The kernel will disable it
+ * by default on NFS sockets too.
+ */
+ if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &one, sizeof one) < 0){
+ syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket");
+ exit(1);
+ }
+ if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &one, sizeof one) < 0){
+ syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket");
+ exit(1);
+ }
+ udpconf = getnetconfigent("udp");
+ tcpconf = getnetconfigent("tcp");
+ udp6conf = getnetconfigent("udp6");
+ tcp6conf = getnetconfigent("tcp6");
if (!resvport_only) {
mib[0] = CTL_VFS;
mib[1] = vfc.vfc_typenum;
@@ -322,17 +388,90 @@ main(argc, argv)
syslog(LOG_ERR, "can't create socket");
exit(1);
}
- pmap_unset(RPCPROG_MNT, 1);
- pmap_unset(RPCPROG_MNT, 3);
- if (!force_v2)
- if (!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
- !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
- syslog(LOG_ERR, "can't register mount");
- exit(1);
- }
- if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
- !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP)) {
- syslog(LOG_ERR, "can't register mount");
+ if (udpsock != -1 && udpconf != NULL) {
+ bindresvport(udpsock, NULL);
+ udptransp = svc_dg_create(udpsock, 0, 0);
+ if (udptransp != NULL) {
+ if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, udpconf))
+ syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, udpconf))
+ syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create UDP services");
+
+ }
+ if (tcpsock != -1 && tcpconf != NULL) {
+ bindresvport(tcpsock, NULL);
+ listen(tcpsock, SOMAXCONN);
+ tcptransp = svc_vc_create(tcpsock, 0, 0);
+ if (tcptransp != NULL) {
+ if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, tcpconf))
+ syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, tcpconf))
+ syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create TCP service");
+
+ }
+ if (udp6sock != -1 && udp6conf != NULL) {
+ bindresvport(udp6sock, NULL);
+ udp6transp = svc_dg_create(udp6sock, 0, 0);
+ if (udp6transp != NULL) {
+ if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, udp6conf))
+ syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, udp6conf))
+ syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create UDP6 service");
+
+ }
+ if (tcp6sock != -1 && tcp6conf != NULL) {
+ bindresvport(tcp6sock, NULL);
+ listen(tcp6sock, SOMAXCONN);
+ tcp6transp = svc_vc_create(tcp6sock, 0, 0);
+ if (tcp6transp != NULL) {
+ if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1,
+ mntsrv, tcp6conf))
+ syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service");
+ else
+ xcreated++;
+ if (!force_v2) {
+ if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3,
+ mntsrv, tcp6conf))
+ syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service");
+ else
+ xcreated++;
+ }
+ } else
+ syslog(LOG_WARNING, "can't create TCP6 service");
+
+ }
+ if (xcreated == 0) {
+ syslog(LOG_ERR, "could not create any services");
exit(1);
}
svc_run();
@@ -361,20 +500,38 @@ mntsrv(rqstp, transp)
struct fhreturn fhr;
struct stat stb;
struct statfs fsb;
- struct hostent *hp;
- struct in_addr saddrin;
- u_int32_t saddr;
+ struct addrinfo *ai;
+ char host[NI_MAXHOST], numerichost[NI_MAXHOST];
+ int lookup_failed = 1;
+ struct sockaddr *saddr;
u_short sport;
char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN];
int bad = 0, defset, hostset;
sigset_t sighup_mask;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
- saddr = transp->xp_raddr.sin_addr.s_addr;
- saddrin = transp->xp_raddr.sin_addr;
- sport = ntohs(transp->xp_raddr.sin_port);
- hp = (struct hostent *)NULL;
+ saddr = svc_getrpccaller(transp)->buf;
+ switch (saddr->sa_family) {
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)saddr;
+ sport = ntohs(sin6->sin6_port);
+ break;
+ case AF_INET:
+ sin = (struct sockaddr_in *)saddr;
+ sport = ntohs(sin->sin_port);
+ break;
+ default:
+ syslog(LOG_ERR, "request from unknown address family");
+ return;
+ }
+ lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host,
+ NULL, 0, 0);
+ getnameinfo(saddr, saddr->sa_len, numerichost,
+ sizeof numerichost, NULL, 0, NI_NUMERICHOST);
+ ai = NULL;
switch (rqstp->rq_proc) {
case NULLPROC:
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
@@ -384,13 +541,13 @@ mntsrv(rqstp, transp)
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"mount request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_getargs(transp, xdr_dir, rpcpath)) {
syslog(LOG_NOTICE, "undecodable mount request from %s",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_decode(transp);
return;
}
@@ -403,12 +560,12 @@ mntsrv(rqstp, transp)
if (realpath(rpcpath, dirpath) == NULL ||
stat(dirpath, &stb) < 0 ||
(!S_ISDIR(stb.st_mode) &&
- (dir_only || !S_ISREG(stb.st_mode))) ||
+ (dir_only || !S_ISREG(stb.st_mode))) ||
statfs(dirpath, &fsb) < 0) {
chdir("/"); /* Just in case realpath doesn't */
syslog(LOG_NOTICE,
"mount request from %s for non existent path %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
if (debug)
warnx("stat failed on %s", dirpath);
bad = ENOENT; /* We will send error reply later */
@@ -420,9 +577,9 @@ mntsrv(rqstp, transp)
hostset = defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
- chk_host(dp, saddr, &defset, &hostset)) ||
- (defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
- scan_tree(ep->ex_dirl, saddr) == 0))) {
+ chk_host(dp, saddr, &defset, &hostset)) ||
+ (defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
+ scan_tree(ep->ex_dirl, saddr) == 0))) {
if (bad) {
if (!svc_sendreply(transp, xdr_long,
(caddr_t)&bad))
@@ -448,25 +605,21 @@ mntsrv(rqstp, transp)
}
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
syslog(LOG_ERR, "can't send reply");
- if (hp == NULL)
- hp = gethostbyaddr((caddr_t)&saddr,
- sizeof(saddr), AF_INET);
- if (hp)
- add_mlist(hp->h_name, dirpath);
+ if (!lookup_failed)
+ add_mlist(host, dirpath);
else
- add_mlist(inet_ntoa(saddrin),
- dirpath);
+ add_mlist(numerichost, dirpath);
if (debug)
warnx("mount successful");
if (log)
syslog(LOG_NOTICE,
"mount request succeeded from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
} else {
bad = EACCES;
syslog(LOG_NOTICE,
"mount request denied from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
}
if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad))
@@ -479,56 +632,54 @@ mntsrv(rqstp, transp)
else if (log)
syslog(LOG_NOTICE,
"dump request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
case RPCMNT_UMOUNT:
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"umount request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_getargs(transp, xdr_dir, rpcpath)) {
syslog(LOG_NOTICE, "undecodable umount request from %s",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_decode(transp);
return;
}
if (realpath(rpcpath, dirpath) == NULL) {
syslog(LOG_NOTICE, "umount request from %s "
"for non existent path %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
}
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
syslog(LOG_ERR, "can't send reply");
- hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
- if (hp)
- del_mlist(hp->h_name, dirpath);
- del_mlist(inet_ntoa(saddrin), dirpath);
+ if (!lookup_failed)
+ del_mlist(host, dirpath, saddr);
+ del_mlist(numerichost, dirpath, saddr);
if (log)
syslog(LOG_NOTICE,
"umount request succeeded from %s for %s",
- inet_ntoa(saddrin), dirpath);
+ numerichost, dirpath);
return;
case RPCMNT_UMNTALL:
if (sport >= IPPORT_RESERVED && resvport_only) {
syslog(LOG_NOTICE,
"umountall request from %s from unprivileged port",
- inet_ntoa(saddrin));
+ numerichost);
svcerr_weakauth(transp);
return;
}
if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))
syslog(LOG_ERR, "can't send reply");
- hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
- if (hp)
- del_mlist(hp->h_name, (char *)NULL);
- del_mlist(inet_ntoa(saddrin), (char *)NULL);
+ if (!lookup_failed)
+ del_mlist(host, NULL, saddr);
+ del_mlist(numerichost, NULL, saddr);
if (log)
syslog(LOG_NOTICE,
"umountall request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
case RPCMNT_EXPORT:
if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL))
@@ -536,7 +687,7 @@ mntsrv(rqstp, transp)
if (log)
syslog(LOG_NOTICE,
"export request succeeded from %s",
- inet_ntoa(saddrin));
+ numerichost);
return;
default:
svcerr_noproc(transp);
@@ -690,7 +841,7 @@ put_exlist(dp, xdrsp, adp, putdefp)
if (grp->gr_type == GT_HOST) {
if (!xdr_bool(xdrsp, &true))
return (1);
- strp = grp->gr_ptr.gt_hostent->h_name;
+ strp = grp->gr_ptr.gt_addrinfo->ai_canonname;
if (!xdr_string(xdrsp, &strp,
RPCMNT_NAMELEN))
return (1);
@@ -732,7 +883,7 @@ get_exportlist()
struct exportlist **epp;
struct dirlist *dirhead;
struct statfs fsb, *fsp;
- struct hostent *hpe;
+ struct addrinfo *ai;
struct xucred anon;
char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;
int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp;
@@ -786,7 +937,7 @@ get_exportlist()
fsp->f_flags | MNT_UPDATE,
(caddr_t)&targs) < 0)
syslog(LOG_ERR, "can't delete exports for %s",
- fsp->f_mntonname);
+ fsp->f_mntonname);
}
fsp++;
}
@@ -874,9 +1025,9 @@ get_exportlist()
else
out_of_mem();
if (debug)
- warnx("making new ep fs=0x%x,0x%x",
- fsb.f_fsid.val[0],
- fsb.f_fsid.val[1]);
+ warnx("making new ep fs=0x%x,0x%x",
+ fsb.f_fsid.val[0],
+ fsb.f_fsid.val[1]);
} else if (debug)
warnx("found ep fs=0x%x,0x%x",
fsb.f_fsid.val[0],
@@ -944,14 +1095,17 @@ get_exportlist()
if (debug)
warnx("adding a default entry");
/* add a default group and make the grp list NULL */
- hpe = (struct hostent *)malloc(sizeof(struct hostent));
- if (hpe == (struct hostent *)NULL)
- out_of_mem();
- hpe->h_name = strdup("Default");
- hpe->h_addrtype = AF_INET;
- hpe->h_length = sizeof (u_int32_t);
- hpe->h_addr_list = (char **)NULL;
- grp->gr_ptr.gt_hostent = hpe;
+ ai = malloc(sizeof(struct addrinfo));
+ ai->ai_flags = 0;
+ ai->ai_family = AF_INET; /* XXXX */
+ ai->ai_socktype = SOCK_DGRAM;
+ /* setting the length to 0 will match anything */
+ ai->ai_addrlen = 0;
+ ai->ai_flags = AI_CANONNAME;
+ ai->ai_canonname = strdup("Default");
+ ai->ai_addr = NULL;
+ ai->ai_next = NULL;
+ grp->gr_ptr.gt_addrinfo = ai;
/*
* Don't allow a network export coincide with a list of
@@ -961,13 +1115,13 @@ get_exportlist()
getexp_err(ep, tgrp);
goto nextline;
- /*
- * If an export list was specified on this line, make sure
+ /*
+ * If an export list was specified on this line, make sure
* that we have at least one valid entry, otherwise skip it.
*/
} else {
grp = tgrp;
- while (grp && grp->gr_type == GT_IGNORE)
+ while (grp && grp->gr_type == GT_IGNORE)
grp = grp->gr_next;
if (! grp) {
getexp_err(ep, tgrp);
@@ -1219,19 +1373,27 @@ add_dlist(dpp, newdp, grp, flags)
/*
* Search for a dirpath on the export point.
*/
+void *
+test()
+{
+}
+
+/*
+ * Search for a dirpath on the export point.
+ */
struct dirlist *
-dirp_search(dp, dirpath)
+dirp_search(dp, dirp)
struct dirlist *dp;
- char *dirpath;
+ char *dirp;
{
int cmp;
if (dp) {
- cmp = strcmp(dp->dp_dirp, dirpath);
+ cmp = strcmp(dp->dp_dirp, dirp);
if (cmp > 0)
- return (dirp_search(dp->dp_left, dirpath));
+ return (dirp_search(dp->dp_left, dirp));
else if (cmp < 0)
- return (dirp_search(dp->dp_right, dirpath));
+ return (dirp_search(dp->dp_right, dirp));
else
return (dp);
}
@@ -1239,18 +1401,59 @@ dirp_search(dp, dirpath)
}
/*
+ * Some helper functions for netmasks. They all assume masks in network
+ * order (big endian).
+ */
+static int
+bitcmp(void *dst, void *src, int bitlen)
+{
+ int i;
+ u_int8_t *p1 = dst, *p2 = src;
+ u_int8_t bitmask;
+ int bytelen, bitsleft;
+
+ bytelen = bitlen / 8;
+ bitsleft = bitlen % 8;
+
+ if (debug) {
+ printf("comparing:\n");
+ for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++)
+ printf("%02x", p1[i]);
+ printf("\n");
+ for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++)
+ printf("%02x", p2[i]);
+ printf("\n");
+ }
+
+ for (i = 0; i < bytelen; i++) {
+ if (*p1 != *p2)
+ return 1;
+ p1++;
+ p2++;
+ }
+
+ for (i = 0; i < bitsleft; i++) {
+ bitmask = 1 << (7 - i);
+ if ((*p1 & bitmask) != (*p2 & bitmask))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* Scan for a host match in a directory tree.
*/
int
chk_host(dp, saddr, defsetp, hostsetp)
struct dirlist *dp;
- u_int32_t saddr;
+ struct sockaddr *saddr;
int *defsetp;
int *hostsetp;
{
struct hostlist *hp;
struct grouplist *grp;
- u_int32_t **addrp;
+ struct addrinfo *ai;
if (dp) {
if (dp->dp_flag & DP_DEFSET)
@@ -1260,22 +1463,22 @@ chk_host(dp, saddr, defsetp, hostsetp)
grp = hp->ht_grp;
switch (grp->gr_type) {
case GT_HOST:
- addrp = (u_int32_t **)
- grp->gr_ptr.gt_hostent->h_addr_list;
- while (*addrp) {
- if (**addrp == saddr) {
- *hostsetp = (hp->ht_flag | DP_HOSTSET);
- return (1);
+ ai = grp->gr_ptr.gt_addrinfo;
+ for (; ai; ai = ai->ai_next) {
+ if (!sacmp(ai->ai_addr, saddr)) {
+ *hostsetp =
+ (hp->ht_flag | DP_HOSTSET);
+ return (1);
+ }
}
- addrp++;
- }
break;
case GT_NET:
- if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
- grp->gr_ptr.gt_net.nt_net) {
- *hostsetp = (hp->ht_flag | DP_HOSTSET);
- return (1);
- }
+ if (!netpartcmp(saddr,
+ (struct sockaddr *) &grp->gr_ptr.gt_net.nt_net,
+ grp->gr_ptr.gt_net.nt_mask)) {
+ *hostsetp = (hp->ht_flag | DP_HOSTSET);
+ return (1);
+ }
break;
};
hp = hp->ht_next;
@@ -1290,7 +1493,7 @@ chk_host(dp, saddr, defsetp, hostsetp)
int
scan_tree(dp, saddr)
struct dirlist *dp;
- u_int32_t saddr;
+ struct sockaddr *saddr;
{
int defset, hostset;
@@ -1392,6 +1595,11 @@ do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr)
opt_flags |= OP_MASK;
} else if (cpoptarg && (!strcmp(cpopt, "network") ||
!strcmp(cpopt, "n"))) {
+ if (strchr(cpoptarg, '/') != NULL) {
+ if (debug)
+ fprintf(stderr, "setting OP_MASKLEN\n");
+ opt_flags |= OP_MASKLEN;
+ }
if (grp->gr_type != GT_NULL) {
syslog(LOG_ERR, "network/host conflict");
return (1);
@@ -1442,84 +1650,40 @@ get_host(cp, grp, tgrp)
struct grouplist *tgrp;
{
struct grouplist *checkgrp;
- struct hostent *hp, *nhp;
- char **addrp, **naddrp;
- struct hostent t_host;
+ struct addrinfo *ai, hints;
+ int ecode;
+ char host[NI_MAXHOST];
int i;
- u_int32_t saddr;
char *aptr[2];
- if (grp->gr_type != GT_NULL)
+ if (grp->gr_type != GT_NULL) {
+ syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp);
return (1);
- if ((hp = gethostbyname(cp)) == NULL) {
- if (isdigit(*cp)) {
- saddr = inet_addr(cp);
- if (saddr == -1) {
- syslog(LOG_ERR, "inet_addr failed for %s", cp);
- return (1);
- }
- if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
- AF_INET)) == NULL) {
- hp = &t_host;
- hp->h_name = cp;
- hp->h_addrtype = AF_INET;
- hp->h_length = sizeof (u_int32_t);
- hp->h_addr_list = aptr;
- aptr[0] = (char *)&saddr;
- aptr[1] = (char *)NULL;
- }
- } else {
- syslog(LOG_ERR, "gethostbyname failed for %s", cp);
- return (1);
- }
}
- /*
- * Sanity check: make sure we don't already have an entry
- * for this host in the grouplist.
- */
- checkgrp = tgrp;
- while (checkgrp != NULL) {
- if (checkgrp->gr_type == GT_HOST &&
- checkgrp->gr_ptr.gt_hostent != NULL &&
- (!strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name)
- || *(u_int32_t *)checkgrp->gr_ptr.gt_hostent->h_addr ==
- *(u_int32_t *)hp->h_addr)) {
- grp->gr_type = GT_IGNORE;
- return(0);
- }
- checkgrp = checkgrp->gr_next;
- }
-
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(cp, NULL, &hints, &ai);
+ if (ecode != 0) {
+ syslog(LOG_ERR,"can't get address info for "
+ "host %s", cp);
+ return 1;
+ }
grp->gr_type = GT_HOST;
- nhp = grp->gr_ptr.gt_hostent = (struct hostent *)
- malloc(sizeof(struct hostent));
- if (nhp == (struct hostent *)NULL)
- out_of_mem();
- memmove(nhp, hp, sizeof(struct hostent));
- i = strlen(hp->h_name)+1;
- nhp->h_name = (char *)malloc(i);
- if (nhp->h_name == (char *)NULL)
- out_of_mem();
- memmove(nhp->h_name, hp->h_name, i);
- addrp = hp->h_addr_list;
- i = 1;
- while (*addrp++)
- i++;
- naddrp = nhp->h_addr_list = (char **)malloc(i*sizeof(char *));
- if (naddrp == (char **)NULL)
- out_of_mem();
- addrp = hp->h_addr_list;
- while (*addrp) {
- *naddrp = (char *)malloc(hp->h_length);
- if (*naddrp == (char *)NULL)
- out_of_mem();
- memmove(*naddrp, *addrp, hp->h_length);
- addrp++;
- naddrp++;
- }
- *naddrp = (char *)NULL;
- if (debug)
- warnx("got host %s", hp->h_name);
+ grp->gr_ptr.gt_addrinfo = ai;
+ while (ai != NULL) {
+ if (ai->ai_canonname == NULL) {
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host,
+ sizeof host, NULL, 0, ninumeric) != 0)
+ strlcpy(host, "?", sizeof(host));
+ ai->ai_canonname = strdup(host);
+ ai->ai_flags |= AI_CANONNAME;
+ } else
+ ai->ai_flags &= ~AI_CANONNAME;
+ if (debug)
+ (void)fprintf(stderr, "got host %s\n", ai->ai_canonname);
+ ai = ai->ai_next;
+ }
return (0);
}
@@ -1597,68 +1761,64 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
int dirplen;
struct statfs *fsb;
{
- char *cp = (char *)NULL;
- u_int32_t **addrp;
+ struct sockaddr *addrp;
+ struct sockaddr_storage ss;
+ struct addrinfo *ai;
+ int addrlen;
+ char *cp = NULL;
int done;
char savedc = '\0';
- struct sockaddr_in sin, imask;
union {
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
+ struct adosfs_args aa;
#endif
struct ntfs_args na;
} args;
- u_int32_t net;
args.ua.fspec = 0;
args.ua.export.ex_flags = exflags;
args.ua.export.ex_anon = *anoncrp;
args.ua.export.ex_indexfile = ep->ex_indexfile;
- memset(&sin, 0, sizeof(sin));
- memset(&imask, 0, sizeof(imask));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- imask.sin_family = AF_INET;
- imask.sin_len = sizeof(sin);
- if (grp->gr_type == GT_HOST)
- addrp = (u_int32_t **)grp->gr_ptr.gt_hostent->h_addr_list;
- else
- addrp = (u_int32_t **)NULL;
+ if (grp->gr_type == GT_HOST) {
+ ai = grp->gr_ptr.gt_addrinfo;
+ addrp = ai->ai_addr;
+ addrlen = ai->ai_addrlen;
+ } else
+ addrp = NULL;
done = FALSE;
while (!done) {
switch (grp->gr_type) {
case GT_HOST:
- if (addrp) {
- sin.sin_addr.s_addr = **addrp;
- args.ua.export.ex_addrlen = sizeof(sin);
- } else
- args.ua.export.ex_addrlen = 0;
- args.ua.export.ex_addr = (struct sockaddr *)&sin;
+ if (addrp != NULL && addrp->sa_family == AF_INET6 &&
+ have_v6 == 0)
+ goto skip;
+ args.ua.export.ex_addr = addrp;
+ args.ua.export.ex_addrlen = addrlen;
args.ua.export.ex_masklen = 0;
break;
case GT_NET:
- if (grp->gr_ptr.gt_net.nt_mask)
- imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask;
- else {
- net = ntohl(grp->gr_ptr.gt_net.nt_net);
- if (IN_CLASSA(net))
- imask.sin_addr.s_addr = inet_addr("255.0.0.0");
- else if (IN_CLASSB(net))
- imask.sin_addr.s_addr =
- inet_addr("255.255.0.0");
- else
- imask.sin_addr.s_addr =
- inet_addr("255.255.255.0");
- grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr;
+ args.ua.export.ex_addr = (struct sockaddr *)
+ &grp->gr_ptr.gt_net.nt_net;
+ if (args.ua.export.ex_addr->sa_family == AF_INET6 &&
+ have_v6 == 0)
+ goto skip;
+ args.ua.export.ex_addrlen =
+ args.ua.export.ex_addr->sa_len;
+ memset(&ss, 0, sizeof ss);
+ ss.ss_family = args.ua.export.ex_addr->sa_family;
+ ss.ss_len = args.ua.export.ex_addr->sa_len;
+ if (allones(&ss, grp->gr_ptr.gt_net.nt_mask) != 0) {
+ syslog(LOG_ERR, "Bad network flag");
+ if (cp)
+ *cp = savedc;
+ return (1);
}
- sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net;
- args.ua.export.ex_addr = (struct sockaddr *)&sin;
- args.ua.export.ex_addrlen = sizeof (sin);
- args.ua.export.ex_mask = (struct sockaddr *)&imask;
- args.ua.export.ex_masklen = sizeof (imask);
+ args.ua.export.ex_mask = (struct sockaddr *)&ss;
+ args.ua.export.ex_masklen = ss.ss_len;
break;
case GT_IGNORE:
return(0);
@@ -1678,7 +1838,7 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
* exportable file systems and not just "ufs".
*/
while (mount(fsb->f_fstypename, dirp,
- fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
+ fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
if (cp)
*cp-- = savedc;
else
@@ -1707,10 +1867,15 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
savedc = *cp;
*cp = '\0';
}
+skip:
if (addrp) {
- ++addrp;
- if (*addrp == (u_int32_t *)NULL)
+ ai = ai->ai_next;
+ if (ai == NULL)
done = TRUE;
+ else {
+ addrp = ai->ai_addr;
+ addrlen = ai->ai_addrlen;
+ }
} else
done = TRUE;
}
@@ -1729,47 +1894,105 @@ get_net(cp, net, maskflg)
int maskflg;
{
struct netent *np;
- long netaddr;
- struct in_addr inetaddr, inetaddr2;
- char *name;
+ char *name, *p, *prefp;
+ struct sockaddr_in sin, *sinp;
+ struct sockaddr *sa;
+ struct addrinfo hints, *ai = NULL;
+ char netname[NI_MAXHOST];
+ long preflen;
+ int ecode;
+
+ if ((opt_flags & OP_MASKLEN) && !maskflg) {
+ p = strchr(cp, '/');
+ *p = '\0';
+ prefp = p + 1;
+ }
- if (isdigit(*cp) && ((netaddr = inet_network(cp)) != -1)) {
- inetaddr = inet_makeaddr(netaddr, 0);
- /*
- * Due to arbitrary subnet masks, you don't know how many
- * bits to shift the address to make it into a network,
- * however you do know how to make a network address into
- * a host with host == 0 and then compare them.
- * (What a pest)
- */
- if (!maskflg) {
- setnetent(0);
- while ((np = getnetent())) {
- inetaddr2 = inet_makeaddr(np->n_net, 0);
- if (inetaddr2.s_addr == inetaddr.s_addr)
- break;
- }
- endnetent();
- }
- } else if ((np = getnetbyname(cp)) != NULL) {
- inetaddr = inet_makeaddr(np->n_net, 0);
+ if ((np = getnetbyname(cp)) != NULL) {
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof sin;
+ sin.sin_addr = inet_makeaddr(np->n_net, 0);
+ sa = (struct sockaddr *)&sin;
+ } else if (isdigit(*cp)) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(cp, NULL, &hints, &ai) != 0) {
+ /*
+ * If getaddrinfo() failed, try the inet4 network
+ * notation with less than 3 dots.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof sin;
+ sin.sin_addr = inet_makeaddr(inet_network(cp),0);
+ if (debug)
+ fprintf(stderr, "get_net: v4 addr %x\n",
+ sin.sin_addr.s_addr);
+ sa = (struct sockaddr *)&sin;
+ } else
+ sa = ai->ai_addr;
+ } else if (isxdigit(*cp) || *cp == ':') {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(cp, NULL, &hints, &ai) == 0)
+ sa = ai->ai_addr;
+ else
+ goto fail;
} else
- return (1);
+ goto fail;
+
+ ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname,
+ NULL, 0, ninumeric);
+ if (ecode != 0)
+ goto fail;
if (maskflg)
- net->nt_mask = inetaddr.s_addr;
+ net->nt_mask = countones(sa);
else {
+ if (opt_flags & OP_MASKLEN) {
+ preflen = strtol(prefp, NULL, 10);
+ if (preflen == LONG_MIN && errno == ERANGE)
+ goto fail;
+ net->nt_mask = (int)preflen;
+ *p = '/';
+ }
+
if (np)
name = np->n_name;
+ else {
+ if (getnameinfo(sa, sa->sa_len, netname, sizeof netname,
+ NULL, 0, ninumeric) != 0)
+ strlcpy(netname, "?", sizeof(netname));
+ name = netname;
+ }
+ net->nt_name = strdup(name);
+ memcpy(&net->nt_net, sa, sa->sa_len);
+ }
+
+ if (!maskflg && sa->sa_family == AF_INET &&
+ !(opt_flags & (OP_MASK|OP_MASKLEN))) {
+ sinp = (struct sockaddr_in *)sa;
+ if (IN_CLASSA(sinp->sin_addr.s_addr))
+ net->nt_mask = 8;
+ else if (IN_CLASSB(sinp->sin_addr.s_addr))
+ net->nt_mask = 16;
+ else if (IN_CLASSC(sinp->sin_addr.s_addr))
+ net->nt_mask = 24;
+ else if (IN_CLASSD(sinp->sin_addr.s_addr))
+ net->nt_mask = 28;
else
- name = inet_ntoa(inetaddr);
- net->nt_name = (char *)malloc(strlen(name) + 1);
- if (net->nt_name == (char *)NULL)
- out_of_mem();
- strcpy(net->nt_name, name);
- net->nt_net = inetaddr.s_addr;
+ net->nt_mask = 32; /* XXX */
}
- return (0);
+
+ if (ai)
+ freeaddrinfo(ai);
+ return 0;
+
+fail:
+ if (ai)
+ freeaddrinfo(ai);
+ return 1;
}
/*
@@ -1958,15 +2181,28 @@ get_mountlist()
fclose(mlfile);
}
-void
-del_mlist(hostp, dirp)
+int
+del_mlist(hostp, dirp, saddr)
char *hostp, *dirp;
+ struct sockaddr *saddr;
{
struct mountlist *mlp, **mlpp;
struct mountlist *mlp2;
+ u_short sport;
FILE *mlfile;
int fnd = 0;
-
+ char host[NI_MAXHOST];
+
+ switch (saddr->sa_family) {
+ case AF_INET6:
+ sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port);
+ break;
+ case AF_INET:
+ sport = ntohs(((struct sockaddr_in *)saddr)->sin_port);
+ break;
+ default:
+ return -1;
+ }
mlpp = &mlhead;
mlp = mlhead;
while (mlp) {
@@ -2034,17 +2270,11 @@ void
free_grp(grp)
struct grouplist *grp;
{
- char **addrp;
+ struct addrinfo *ai;
if (grp->gr_type == GT_HOST) {
- if (grp->gr_ptr.gt_hostent->h_name) {
- addrp = grp->gr_ptr.gt_hostent->h_addr_list;
- while (addrp && *addrp)
- free(*addrp++);
- free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list);
- free(grp->gr_ptr.gt_hostent->h_name);
- }
- free((caddr_t)grp->gr_ptr.gt_hostent);
+ if (grp->gr_ptr.gt_addrinfo != NULL)
+ freeaddrinfo(grp->gr_ptr.gt_addrinfo);
} else if (grp->gr_type == GT_NET) {
if (grp->gr_ptr.gt_net.nt_name)
free(grp->gr_ptr.gt_net.nt_name);
@@ -2093,7 +2323,6 @@ check_options(dp)
/*
* Check an absolute directory path for any symbolic links. Return true
- * if no symbolic links are found.
*/
int
check_dirpath(dirp)
@@ -2134,3 +2363,146 @@ get_num(cp)
}
return (res);
}
+
+static int
+netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen)
+{
+ void *src, *dst;
+
+ if (s1->sa_family != s2->sa_family)
+ return 1;
+
+ switch (s1->sa_family) {
+ case AF_INET:
+ src = &((struct sockaddr_in *)s1)->sin_addr;
+ dst = &((struct sockaddr_in *)s2)->sin_addr;
+ if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8)
+ return 1;
+ break;
+ case AF_INET6:
+ src = &((struct sockaddr_in6 *)s1)->sin6_addr;
+ dst = &((struct sockaddr_in6 *)s2)->sin6_addr;
+ if (((struct sockaddr_in6 *)s1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)s2)->sin6_scope_id)
+ return 1;
+ if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8)
+ return 1;
+ break;
+ default:
+ return 1;
+ }
+
+ return bitcmp(src, dst, bitlen);
+}
+
+static int
+allones(struct sockaddr_storage *ssp, int bitlen)
+{
+ u_int8_t *p;
+ int bytelen, bitsleft, i;
+ int zerolen;
+
+ switch (ssp->ss_family) {
+ case AF_INET:
+ p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr;
+ zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr);
+ break;
+ case AF_INET6:
+ p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr;
+ zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr);
+ break;
+ default:
+ return -1;
+ }
+
+ memset(p, 0, zerolen);
+
+ bytelen = bitlen / 8;
+ bitsleft = bitlen % 8;
+
+ if (bytelen > zerolen)
+ return -1;
+
+ for (i = 0; i < bytelen; i++)
+ *p++ = 0xff;
+
+ for (i = 0; i < bitsleft; i++)
+ *p |= 1 << (7 - i);
+
+ return 0;
+}
+
+static int
+countones(struct sockaddr *sa)
+{
+ void *mask;
+ int i, bits = 0, bytelen;
+ u_int8_t *p;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr;
+ bytelen = 4;
+ break;
+ case AF_INET6:
+ mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr;
+ bytelen = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ p = mask;
+
+ for (i = 0; i < bytelen; i++, p++) {
+ if (*p != 0xff) {
+ for (bits = 0; bits < 8; bits++) {
+ if (!(*p & (1 << (7 - bits))))
+ break;
+ }
+ break;
+ }
+ }
+
+ return (i * 8 + bits);
+}
+
+static int
+sacmp(struct sockaddr *sa1, struct sockaddr *sa2)
+{
+ void *p1, *p2;
+ int len;
+
+ if (sa1->sa_family != sa2->sa_family)
+ return 1;
+
+ switch (sa1->sa_family) {
+ case AF_INET:
+ p1 = &((struct sockaddr_in *)sa1)->sin_addr;
+ p2 = &((struct sockaddr_in *)sa2)->sin_addr;
+ len = 4;
+ break;
+ case AF_INET6:
+ p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
+ p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
+ len = 16;
+ if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
+ return 1;
+ break;
+ default:
+ return 1;
+ }
+
+ return memcmp(p1, p2, len);
+}
+
+void terminate(sig)
+int sig;
+{
+ close(mountdlockfd);
+ unlink(MOUNTDLOCK);
+ pmap_unset(RPCPROG_MNT, 1);
+ pmap_unset(RPCPROG_MNT, 3);
+ exit (0);
+}
diff --git a/usr.sbin/nfsd/nfsd.8 b/usr.sbin/nfsd/nfsd.8
index fb44149bb4d8..0031ea1b926e 100644
--- a/usr.sbin/nfsd/nfsd.8
+++ b/usr.sbin/nfsd/nfsd.8
@@ -42,7 +42,7 @@
server
.Sh SYNOPSIS
.Nm
-.Op Fl arut
+.Op Fl ardut
.Op Fl n Ar num_servers
.Op Fl h Ar bindip
.Sh DESCRIPTION
@@ -64,13 +64,19 @@ The following options are available:
Register the
.Tn NFS
service with
-.Xr portmap 8
+.Xr rpcbind 8
without creating any servers.
This option can be used along with the
.Fl u
or
.Fl t
-options to re-register NFS if the portmap server is restarted.
+options to re-register NFS if the rpcbind server is restarted.
+.It Fl d
+Unregister the
+.Tn NFS
+service with
+.Xr rpcbind 8
+without creating any servers.
.It Fl n
Specifies how many servers to create.
.It Fl h Ar bindip
@@ -147,6 +153,16 @@ that the NFS sockets can only be accessed by the inside interface.
would then be used to block nfs-related packets that come in on the outside
interface.
.Pp
+.Nm
+has to be terminated with SIGUSR1 and cannot be killed with SIGTERM oder SIGQUIT.
+.Nm
+needs to ignore these signals in order to stay alive as long
+as possible during a shutdown, otherwise loopback mounts will
+not be able to unmount. If you have to kill
+.Nm
+just do a
+.Dq Li "kill -USR1 <PID of master nfsd>"
+.Pp
The
.Nm
utility exits 0 on success, and >0 if an error occurs.
@@ -156,7 +172,7 @@ utility exits 0 on success, and >0 if an error occurs.
.Xr kldload 8 ,
.Xr mountd 8 ,
.Xr nfsiod 8 ,
-.Xr portmap 8 ,
+.Xr rpcbind 8 ,
.Xr ipfw 8
.Sh HISTORY
The
diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c
index 2d923a42652b..959f0fb04d18 100644
--- a/usr.sbin/nfsd/nfsd.c
+++ b/usr.sbin/nfsd/nfsd.c
@@ -58,9 +58,6 @@ static const char rcsid[] =
#include <netdb.h>
#include <arpa/inet.h>
-#ifdef ISO
-#include <netiso/iso.h>
-#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
@@ -76,6 +73,7 @@ static const char rcsid[] =
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
+#include <netdb.h>
/* Global defs */
#ifdef DEBUG
@@ -103,15 +101,23 @@ struct timeval ktv;
NFSKERBKEYSCHED_T kerb_keysched;
#endif
-void nonfs __P((int));
-void reapchild __P((int));
-void setbindhost __P((struct sockaddr_in *ia, const char *bindhost));
+#define MAXNFSDCNT 20
+#define DEFNFSDCNT 4
+pid_t children[MAXNFSDCNT]; /* PIDs of children */
+int nfsdcnt; /* number of children */
+
+void cleanup(int);
+void killchildren(void);
+void nonfs (int);
+void reapchild (int);
+int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints);
#ifdef OLD_SETPROCTITLE
#ifdef __FreeBSD__
-void setproctitle __P((char *));
+void setproctitle (char *);
#endif
#endif
-void usage __P((void));
+void unregistration (void);
+void usage (void);
/*
* Nfs server daemon mostly just a user context for nfssvc()
@@ -119,7 +125,7 @@ void usage __P((void));
* 1 - do file descriptor and signal cleanup
* 2 - fork the nfsd(s)
* 3 - create server socket(s)
- * 4 - register socket with portmap
+ * 4 - register socket with rpcbind
*
* For connectionless protocols, just pass the socket into the kernel via.
* nfssvc().
@@ -127,7 +133,8 @@ void usage __P((void));
* socket from accept, pass the msgsock into the kernel via. nfssvc().
* The arguments are:
* -c - support iso cltp clients
- * -r - reregister with portmapper
+ * -r - reregister with rpcbind
+ * -d - unregister with rpcbind
* -t - support tcp nfs clients
* -u - support udp nfs clients
* followed by "n" which is the number of nfsds' to fork off
@@ -138,20 +145,20 @@ main(argc, argv, envp)
char *argv[], *envp[];
{
struct nfsd_args nfsdargs;
- struct sockaddr_in inetaddr, inetpeer;
-#ifdef ISO
- struct sockaddr_iso isoaddr, isopeer;
- char *cp;
-#endif
+ struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
+ struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
+ struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
+ struct sockaddr_in inetpeer;
+ struct sockaddr_in6 inet6peer;
fd_set ready, sockbits;
+ fd_set v4bits, v6bits;
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
- int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
- int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
- int bindhostc = 0, bindanyflag;
+ int nfssvc_flag, on = 1, unregister, reregister, sock;
+ int tcp6sock, ip6flag, tcpflag, tcpsock;
+ int udpflag, ecode, s;
+ int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt;
char **bindhost = NULL;
-#ifdef notyet
- int tp4sock, tpipsock;
-#endif
+ pid_t pid;
#ifdef NFSKERB
struct group *grp;
struct passwd *pwd;
@@ -184,18 +191,11 @@ main(argc, argv, envp)
LastArg = envp[-1] + strlen(envp[-1]);
#endif
-#define MAXNFSDCNT 20
-#define DEFNFSDCNT 4
nfsdcnt = DEFNFSDCNT;
- cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
- bindanyflag = tpipflag = udpflag = 0;
-#ifdef ISO
-#define GETOPT "ach:n:rtu"
-#define USAGE "[-acrtu] [-n num_servers] [-h bindip]"
-#else
-#define GETOPT "ah:n:rtu"
-#define USAGE "[-artu] [-n num_servers] [-h bindip]"
-#endif
+ cltpflag = unregister = reregister = tcpflag = 0;
+ bindanyflag = udpflag = ip6flag = 0;
+#define GETOPT "ah:n:rdtu"
+#define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
while ((ch = getopt(argc, argv, GETOPT)) != -1)
switch (ch) {
case 'a':
@@ -221,25 +221,15 @@ main(argc, argv, envp)
case 'r':
reregister = 1;
break;
+ case 'd':
+ unregister = 1;
+ break;
case 't':
tcpflag = 1;
break;
case 'u':
udpflag = 1;
break;
-#ifdef ISO
- case 'c':
- cltpflag = 1;
- break;
-#ifdef notyet
- case 'i':
- tp4cnt = 1;
- break;
- case 'p':
- tpipcnt = 1;
- break;
-#endif /* notyet */
-#endif /* ISO */
default:
case '?':
usage();
@@ -263,6 +253,13 @@ main(argc, argv, envp)
nfsdcnt = DEFNFSDCNT;
}
}
+ ip6flag = 1;
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0 && (errno == EPROTONOSUPPORT ||
+ errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
+ ip6flag = 0;
+ else
+ close(s);
if (bindhostc == 0 || bindanyflag) {
bindhostc++;
@@ -278,33 +275,126 @@ main(argc, argv, envp)
daemon(0, 0);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGSYS, nonfs);
+ (void)signal(SIGUSR1, cleanup);
+ /*
+ * nfsd sits in the kernel most of the time. It needs
+ * to ignore SIGTERM/SIGQUIT in order to stay alive as long
+ * as possible during a shutdown, otherwise loopback
+ * mounts will not be able to unmount.
+ */
(void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
}
(void)signal(SIGCHLD, reapchild);
-
+ if (unregister) {
+ unregistration();
+ exit (0);
+ }
if (reregister) {
- if (udpflag &&
- (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
- err(1, "can't register with portmap for UDP");
- if (tcpflag &&
- (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
- err(1, "can't register with portmap for TCP");
- exit(0);
+ if (udpflag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp = getnetconfigent("udp");
+ if (nconf_udp == NULL)
+ err(1, "getnetconfigent udp failed");
+ nb_udp.buf = ai_udp->ai_addr;
+ nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
+ err(1, "rpcb_set udp failed");
+ freeaddrinfo(ai_udp);
+ }
+ if (udpflag && ip6flag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp6 = getnetconfigent("udp6");
+ if (nconf_udp6 == NULL)
+ err(1, "getnetconfigent udp6 failed");
+ nb_udp6.buf = ai_udp6->ai_addr;
+ nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
+ err(1, "rpcb_set udp6 failed");
+ freeaddrinfo(ai_udp6);
+ }
+ if (tcpflag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp = getnetconfigent("tcp");
+ if (nconf_tcp == NULL)
+ err(1, "getnetconfigent tcp failed");
+ nb_tcp.buf = ai_tcp->ai_addr;
+ nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
+ err(1, "rpcb_set tcp failed");
+ freeaddrinfo(ai_tcp);
+ }
+ if (tcpflag && ip6flag) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp6 = getnetconfigent("tcp6");
+ if (nconf_tcp6 == NULL)
+ err(1, "getnetconfigent tcp6 failed");
+ nb_tcp6.buf = ai_tcp6->ai_addr;
+ nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
+ err(1, "rpcb_set tcp6 failed");
+ freeaddrinfo(ai_tcp6);
+ }
+ exit (0);
}
+
openlog("nfsd:", LOG_PID, LOG_DAEMON);
for (i = 0; i < nfsdcnt; i++) {
- switch (fork()) {
+ switch ((pid = fork())) {
case -1:
syslog(LOG_ERR, "fork: %m");
+ killchildren();
exit (1);
case 0:
break;
default:
+ children[i] = pid;
continue;
}
@@ -399,182 +489,295 @@ main(argc, argv, envp)
exit(0);
}
- /* If we are serving udp, set up the socket. */
- for (i = 0; udpflag && i < bindhostc; i++) {
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create udp socket");
- exit(1);
- }
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(sock,
- (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register with udp portmap");
- exit(1);
+ if (atexit(killchildren) == -1) {
+ syslog(LOG_ERR, "atexit: %s", strerror(errno));
+ exit(1);
+ }
+ FD_ZERO(&v4bits);
+ FD_ZERO(&v6bits);
+
+ rpcbregcnt = 0;
+ /* Set up the socket for udp and rpcb register it. */
+ if (udpflag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((sock = socket(ai_udp->ai_family,
+ ai_udp->ai_socktype,
+ ai_udp->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create udp socket");
+ exit(1);
+ }
+ if (bind(sock, ai_udp->ai_addr,
+ ai_udp->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind udp addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ freeaddrinfo(ai_udp);
+ nfsdargs.sock = sock;
+ nfsdargs.name = NULL;
+ nfsdargs.namelen = 0;
+ if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+ syslog(LOG_ERR, "can't Add UDP socket");
+ exit(1);
+ }
+ (void)close(sock);
+ }
}
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR, "can't Add UDP socket");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp = getnetconfigent("udp");
+ if (nconf_udp == NULL)
+ err(1, "getnetconfigent udp failed");
+ nb_udp.buf = ai_udp->ai_addr;
+ nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
+ err(1, "rpcb_set udp failed");
+ freeaddrinfo(ai_udp);
}
- (void)close(sock);
}
-#ifdef ISO
- /* If we are serving cltp, set up the socket. */
- if (cltpflag) {
- if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create cltp socket");
- exit(1);
- }
- memset(&isoaddr, 0, sizeof(isoaddr));
- isoaddr.siso_family = AF_ISO;
- isoaddr.siso_tlen = 2;
- cp = TSEL(&isoaddr);
- *cp++ = (NFS_PORT >> 8);
- *cp = (NFS_PORT & 0xff);
- isoaddr.siso_len = sizeof(isoaddr);
- if (bind(sock,
- (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
- syslog(LOG_ERR, "can't bind cltp addr");
- exit(1);
- }
-#ifdef notyet
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register with udp portmap");
- exit(1);
+ /* Set up the socket for udp6 and rpcb register it. */
+ if (udpflag && ip6flag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((sock = socket(ai_udp6->ai_family,
+ ai_udp6->ai_socktype,
+ ai_udp6->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create udp6 socket");
+ exit(1);
+ }
+ if (setsockopt(sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY,
+ &on, sizeof on) < 0) {
+ syslog(LOG_ERR,
+ "can't set v6-only binding for "
+ "udp6 socket: %m");
+ exit(1);
+ }
+ if (bind(sock, ai_udp6->ai_addr,
+ ai_udp6->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind udp6 addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ freeaddrinfo(ai_udp6);
+ nfsdargs.sock = sock;
+ nfsdargs.name = NULL;
+ nfsdargs.namelen = 0;
+ if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+ syslog(LOG_ERR,
+ "can't add UDP6 socket");
+ exit(1);
+ }
+ (void)close(sock);
+ }
}
-#endif /* notyet */
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR, "can't add UDP socket");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo udp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_udp6 = getnetconfigent("udp6");
+ if (nconf_udp6 == NULL)
+ err(1, "getnetconfigent udp6 failed");
+ nb_udp6.buf = ai_udp6->ai_addr;
+ nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
+ err(1, "rpcb_set udp6 failed");
+ freeaddrinfo(ai_udp6);
}
- close(sock);
}
-#endif /* ISO */
-
- /* Now set up the master server socket waiting for tcp connections. */
- on = 1;
- FD_ZERO(&sockbits);
- connect_type_cnt = 0;
- for (i = 0; tcpflag && i < bindhostc; i++) {
- if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- syslog(LOG_ERR, "can't create tcp socket");
- exit(1);
- }
- if (setsockopt(tcpsock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(tcpsock,
- (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (listen(tcpsock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
+
+ /* Set up the socket for tcp and rpcb register it. */
+ if (tcpflag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((tcpsock = socket(AF_INET, SOCK_STREAM,
+ 0)) < 0) {
+ syslog(LOG_ERR,
+ "can't create tpc socket");
+ exit(1);
+ }
+ if (setsockopt(tcpsock, SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_REUSEADDR: %m");
+ if (bind(tcpsock, ai_tcp->ai_addr,
+ ai_tcp->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind tcp addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ if (listen(tcpsock, 5) < 0) {
+ syslog(LOG_ERR, "listen failed");
+ exit(1);
+ }
+ freeaddrinfo(ai_tcp);
+ FD_SET(tcpsock, &sockbits);
+ FD_SET(tcpsock, &v4bits);
+ maxsock = tcpsock;
+ connect_type_cnt++;
+ }
}
- if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
- !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints,
+ &ai_tcp);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp = getnetconfigent("tcp");
+ if (nconf_tcp == NULL)
+ err(1, "getnetconfigent tcp failed");
+ nb_tcp.buf = ai_tcp->ai_addr;
+ nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
+ &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
+ nconf_tcp, &nb_tcp)))
+ err(1, "rpcb_set tcp failed");
+ freeaddrinfo(ai_tcp);
}
- FD_SET(tcpsock, &sockbits);
- maxsock = tcpsock;
- connect_type_cnt++;
}
-#ifdef notyet
- /* Now set up the master server socket waiting for tp4 connections. */
- if (tp4flag) {
- if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
- syslog(LOG_ERR, "can't create tp4 socket");
- exit(1);
- }
- if (setsockopt(tp4sock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- memset(&isoaddr, 0, sizeof(isoaddr));
- isoaddr.siso_family = AF_ISO;
- isoaddr.siso_tlen = 2;
- cp = TSEL(&isoaddr);
- *cp++ = (NFS_PORT >> 8);
- *cp = (NFS_PORT & 0xff);
- isoaddr.siso_len = sizeof(isoaddr);
- if (bind(tp4sock,
- (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tp4 addr");
- exit(1);
- }
- if (listen(tp4sock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
+ /* Set up the socket for tcp6 and rpcb register it. */
+ if (tcpflag && ip6flag) {
+ rpcbreg = 0;
+ for (i = 0; i < bindhostc; i++) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
+ rpcbreg = 1;
+ rpcbregcnt++;
+ if ((tcp6sock = socket(ai_tcp6->ai_family,
+ ai_tcp6->ai_socktype,
+ ai_tcp6->ai_protocol)) < 0) {
+ syslog(LOG_ERR,
+ "can't create tcp6 socket");
+ exit(1);
+ }
+ if (setsockopt(tcp6sock, SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_REUSEADDR: %m");
+ if (setsockopt(tcp6sock, IPPROTO_IPV6,
+ IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
+ syslog(LOG_ERR,
+ "can't set v6-only binding for tcp6 "
+ "socket: %m");
+ exit(1);
+ }
+ if (bind(tcp6sock, ai_tcp6->ai_addr,
+ ai_tcp6->ai_addrlen) < 0) {
+ syslog(LOG_ERR,
+ "can't bind tcp6 addr %s: %m",
+ bindhost[i]);
+ exit(1);
+ }
+ if (listen(tcp6sock, 5) < 0) {
+ syslog(LOG_ERR, "listen failed");
+ exit(1);
+ }
+ freeaddrinfo(ai_tcp6);
+ FD_SET(tcp6sock, &sockbits);
+ FD_SET(tcp6sock, &v6bits);
+ if (maxsock < tcp6sock)
+ maxsock = tcp6sock;
+ connect_type_cnt++;
+ }
}
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
+ if (rpcbreg == 1) {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo tcp6: %s",
+ gai_strerror(ecode));
+ exit(1);
+ }
+ nconf_tcp6 = getnetconfigent("tcp6");
+ if (nconf_tcp6 == NULL)
+ err(1, "getnetconfigent tcp6 failed");
+ nb_tcp6.buf = ai_tcp6->ai_addr;
+ nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
+ if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
+ (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
+ err(1, "rpcb_set tcp6 failed");
+ freeaddrinfo(ai_tcp6);
}
- FD_SET(tp4sock, &sockbits);
- maxsock = tp4sock;
- connect_type_cnt++;
}
- /* Now set up the master server socket waiting for tpip connections. */
- for (i = 0; tpipflag && i < bindhostc; i++) {
- if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
- syslog(LOG_ERR, "can't create tpip socket");
- exit(1);
- }
- if (setsockopt(tpipsock,
- SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
- setbindhost(&inetaddr, bindhost[i]);
- if (bind(tpipsock,
- (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
- exit(1);
- }
- if (listen(tpipsock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- exit(1);
- }
- /*
- * XXX
- * Someday this should probably use "rpcbind", the son of
- * portmap.
- */
- if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
- syslog(LOG_ERR, "can't register tcp with portmap");
- exit(1);
- }
- FD_SET(tpipsock, &sockbits);
- maxsock = tpipsock;
- connect_type_cnt++;
+ if (rpcbregcnt == 0) {
+ syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
+ exit(1);
}
-#endif /* notyet */
- if (connect_type_cnt == 0)
- exit(0);
+ if ((tcpflag) && (connect_type_cnt == 0)) {
+ syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
+ exit(1);
+ }
setproctitle("master");
@@ -591,82 +794,94 @@ main(argc, argv, envp)
exit(1);
}
}
- if (tcpflag && FD_ISSET(tcpsock, &ready)) {
- len = sizeof(inetpeer);
- if ((msgsock = accept(tcpsock,
- (struct sockaddr *)&inetpeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
- }
- memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inetpeer;
- nfsdargs.namelen = sizeof(inetpeer);
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- }
-#ifdef notyet
- if (tp4flag && FD_ISSET(tp4sock, &ready)) {
- len = sizeof(isopeer);
- if ((msgsock = accept(tp4sock,
- (struct sockaddr *)&isopeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
- }
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&isopeer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- }
- if (tpipflag && FD_ISSET(tpipsock, &ready)) {
- len = sizeof(inetpeer);
- if ((msgsock = accept(tpipsock,
- (struct sockaddr *)&inetpeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- exit(1);
+ for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
+ if (FD_ISSET(tcpsock, &ready)) {
+ if (FD_ISSET(tcpsock, &v4bits)) {
+ len = sizeof(inetpeer);
+ if ((msgsock = accept(tcpsock,
+ (struct sockaddr *)&inetpeer, &len)) < 0) {
+ syslog(LOG_ERR, "accept failed: %m");
+ exit(1);
+ }
+ memset(inetpeer.sin_zero, 0,
+ sizeof(inetpeer.sin_zero));
+ if (setsockopt(msgsock, SOL_SOCKET,
+ SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
+ syslog(LOG_ERR,
+ "setsockopt SO_KEEPALIVE: %m");
+ nfsdargs.sock = msgsock;
+ nfsdargs.name = (caddr_t)&inetpeer;
+ nfsdargs.namelen = sizeof(inetpeer);
+ nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+ (void)close(msgsock);
+ } else if (FD_ISSET(tcpsock, &v6bits)) {
+ len = sizeof(inet6peer);
+ if ((msgsock = accept(tcpsock,
+ (struct sockaddr *)&inet6peer,
+ &len)) < 0) {
+ syslog(LOG_ERR,
+ "accept failed: %m");
+ exit(1);
+ }
+ if (setsockopt(msgsock, SOL_SOCKET,
+ SO_KEEPALIVE, (char *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_ERR, "setsockopt "
+ "SO_KEEPALIVE: %m");
+ nfsdargs.sock = msgsock;
+ nfsdargs.name = (caddr_t)&inet6peer;
+ nfsdargs.namelen = sizeof(inet6peer);
+ nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+ (void)close(msgsock);
+ }
}
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inetpeer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
}
-#endif /* notyet */
}
}
-void
-setbindhost(struct sockaddr_in *ia, const char *bindhost)
+int
+setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
{
- ia->sin_family = AF_INET;
- ia->sin_port = htons(NFS_PORT);
- ia->sin_len = sizeof(*ia);
- if (bindhost == NULL || strcmp(bindhost,"*") == 0) {
- ia->sin_addr.s_addr = INADDR_ANY;
- } else {
- if (inet_aton(bindhost, &ia->sin_addr) == 0) {
- struct hostent *he;
-
- he = gethostbyname2(bindhost, ia->sin_family);
- if (he == NULL) {
- syslog(LOG_ERR, "gethostbyname of %s failed", bindhost);
- exit(1);
+ int ecode;
+ u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ const char *hostptr;
+
+ if (bindhost == NULL || strcmp("*", bindhost) == 0)
+ hostptr = NULL;
+ else
+ hostptr = bindhost;
+
+ if (hostptr != NULL) {
+ switch (hints.ai_family) {
+ case AF_INET:
+ if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
+ hints.ai_flags = AI_NUMERICHOST;
+ } else {
+ if (inet_pton(AF_INET6, hostptr,
+ host_addr) == 1)
+ return (1);
+ }
+ break;
+ case AF_INET6:
+ if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
+ hints.ai_flags = AI_NUMERICHOST;
+ } else {
+ if (inet_pton(AF_INET, hostptr,
+ host_addr) == 1)
+ return (1);
}
- bcopy(he->h_addr, &ia->sin_addr, he->h_length);
+ break;
+ default:
}
}
+
+ ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
+ if (ecode != 0) {
+ syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
+ gai_strerror(ecode));
+ return (1);
+ }
+ return (0);
}
void
@@ -691,6 +906,48 @@ reapchild(signo)
while (wait3(NULL, WNOHANG, NULL) > 0);
}
+void
+unregistration()
+{
+ if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
+ (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
+ syslog(LOG_ERR, "rpcb_unset failed");
+}
+
+void
+killchildren()
+{
+ int i;
+ sigset_t sigs;
+
+ sigemptyset(&sigs);
+ /*
+ * Block SIGCHLD to avoid killing a reaped process (although it is
+ * unlikely, the pid might have been reused).
+ */
+ sigaddset(&sigs, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) {
+ syslog(LOG_ERR, "sigprocmask: %s",
+ strerror(errno));
+ return;
+ }
+ for (i = 0; i < nfsdcnt; i++) {
+ if (children[i] > 0)
+ kill(children[i], SIGKILL);
+ }
+ if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) {
+ syslog(LOG_ERR, "sigprocmask: %s", strerror(errno));
+ }
+ unregistration();
+}
+
+void
+cleanup(signo)
+{
+ killchildren();
+ exit (0);
+}
+
#ifdef OLD_SETPROCTITLE
#ifdef __FreeBSD__
void
diff --git a/usr.sbin/portmap/Makefile b/usr.sbin/portmap/Makefile
deleted file mode 100644
index b87cf595a9e4..000000000000
--- a/usr.sbin/portmap/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $FreeBSD$
-
-PROG= portmap
-MAN8= portmap.8
-SRCS= portmap.c from_local.c pmap_check.c
-SUBDIR= pmap_set pmap_dump
-
-CFLAGS+=-DCHECK_PORT -DHOSTS_ACCESS
-DPADD= ${LIBWRAP}
-LDADD= -lwrap
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/portmap/from_local.c b/usr.sbin/portmap/from_local.c
deleted file mode 100644
index 9886f1250b86..000000000000
--- a/usr.sbin/portmap/from_local.c
+++ /dev/null
@@ -1,233 +0,0 @@
- /*
- * Check if an address belongs to the local system. Adapted from:
- *
- * @(#)pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc.
- * @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC.
- */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user or with the express written consent of
- * Sun Microsystems, Inc.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#) from_local.c 1.2 93/11/16 21:50:02";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#ifdef TEST
-#undef perror
-#endif
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/route.h>
-#include <netinet/in.h>
-
-#include "pmap_check.h"
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#define ROUNDUP(x) ((x) ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
-
-/* How many interfaces could there be on a computer? */
-
-#define ESTIMATED_LOCAL 20
-static int num_local = -1;
-static struct in_addr *addrs;
-
-static void
-rtiparse(struct ifa_msghdr *ifam, struct rt_addrinfo *ai)
-{
- char *wp;
- int rtax;
-
- wp = (char *)(ifam + 1);
-
- ai->rti_addrs = ifam->ifam_addrs;
- for (rtax = 0; rtax < sizeof ai->rti_info / sizeof *ai->rti_info; rtax++)
- if (ifam->ifam_addrs & (1 << rtax)) {
- ai->rti_info[rtax] = (struct sockaddr *)wp;
- wp += ROUNDUP(ai->rti_info[rtax]->sa_len);
- } else
- ai->rti_info[rtax] = NULL;
-}
-
-/* find_local - find all IP addresses for this host */
-
-static int
-find_local()
-{
- int mib[6], n, s, alloced;
- size_t needed;
- char *buf, *end, *ptr;
- struct if_msghdr *ifm;
- struct ifa_msghdr *ifam;
- struct rt_addrinfo ai;
- struct ifreq ifr;
- struct sockaddr_dl *dl;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[4] = NET_RT_IFLIST;
- mib[2] = mib[3] = mib[5] = 0;
-
- if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("socket");
- return (0);
- }
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- close(s);
- perror("sysctl(NET_RT_IFLIST)");
- return 0;
- }
- if ((buf = (char *)malloc(needed)) == NULL) {
- close(s);
- perror("malloc");
- return 0;
- }
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
- close(s);
- free(buf);
- perror("sysctl(NET_RT_IFLIST)(after malloc)");
- return 0;
- }
-
- if (addrs) {
- free(addrs);
- addrs = NULL;
- }
- num_local = 0;
- alloced = 0;
- end = buf + needed;
-
- for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
- ifm = (struct if_msghdr *)ptr;
- dl = (struct sockaddr_dl *)(ifm + 1);
-
- if (ifm->ifm_index != dl->sdl_index || dl->sdl_nlen == 0)
- /* Skip over remaining ifa_msghdrs */
- continue;
-
- n = dl->sdl_nlen > sizeof ifr.ifr_name ?
- sizeof ifr.ifr_name : dl->sdl_nlen;
- strncpy(ifr.ifr_name, dl->sdl_data, n);
- if (n < sizeof ifr.ifr_name)
- ifr.ifr_name[n] = '\0';
-
- /* we only want the first address from each interface */
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
- fprintf(stderr, "%.*s: SIOCGIFFLAGS: %s\n", n, ifr.ifr_name,
- strerror(errno));
- else if (ifr.ifr_flags & IFF_UP) { /* active interface */
- ifam = (struct ifa_msghdr *)(ptr + ifm->ifm_msglen);
- while ((char *)ifam < end && ifam->ifam_type == RTM_NEWADDR) {
- rtiparse(ifam, &ai);
-
- if (ai.rti_info[RTAX_IFA] != NULL &&
- ai.rti_info[RTAX_IFA]->sa_family == AF_INET) {
- if (alloced < num_local + 1) {
- alloced += ESTIMATED_LOCAL;
- addrs = (struct in_addr *)realloc(addrs, alloced * sizeof addrs[0]);
- if (addrs == NULL) {
- perror("malloc/realloc");
- num_local = 0;
- break;
- }
- }
- addrs[num_local++] = ((struct sockaddr_in *)
- ai.rti_info[RTAX_IFA])->sin_addr;
-
- }
- ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
- }
- }
- }
- free(buf);
- close(s);
-
- return num_local;
-}
-
-/* from_local - determine whether request comes from the local system */
-
-int
-from_local(addr)
- struct sockaddr_in *addr;
-{
- int i;
-
- if (num_local == -1 && find_local() == 0)
- syslog(LOG_ERR, "cannot find any active local network interfaces");
-
- for (i = 0; i < num_local; i++) {
- if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
- sizeof(struct in_addr)) == 0)
- return (TRUE);
- }
- return (FALSE);
-}
-
-#ifdef TEST
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- char *inet_ntoa();
- int i;
-
- find_local();
- for (i = 0; i < num_local; i++)
- printf("%s\n", inet_ntoa(addrs[i]));
-
- return 0;
-}
-
-#endif
diff --git a/usr.sbin/portmap/pmap_check.c b/usr.sbin/portmap/pmap_check.c
deleted file mode 100644
index 7ad25c9a7743..000000000000
--- a/usr.sbin/portmap/pmap_check.c
+++ /dev/null
@@ -1,263 +0,0 @@
- /*
- * pmap_check - additional portmap security.
- *
- * Always reject non-local requests to update the portmapper tables.
- *
- * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
- * requests would appear to come from the local system, and nfs export
- * restrictions could be bypassed.
- *
- * Refuse to forward requests to the nfsd process.
- *
- * Refuse to forward requests to NIS (YP) daemons; The only exception is the
- * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
- * contact with the NIS server.
- *
- * Always allocate an unprivileged port when forwarding a request.
- *
- * If compiled with -DCHECK_PORT, require that requests to register or
- * unregister a privileged port come from a privileged port. This makes it
- * more difficult to replace a critical service by a trojan.
- *
- * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
- * authorized by the /etc/hosts.{allow,deny} files. The local system is
- * always treated as an authorized host. The access control tables are never
- * consulted for requests from the local system, and are always consulted
- * for requests from other hosts. Access control is based on IP addresses
- * only; attempts to map an address to a host name might cause the
- * portmapper to hang.
- *
- * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
- * Computing Science, Eindhoven University of Technology, The Netherlands.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#) pmap_check.c 1.6 93/11/21 20:58:59";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <syslog.h>
-#include <netdb.h>
-#include <sys/signal.h>
-
-#include "pmap_check.h"
-
-/* Explicit #defines in case the include files are not available. */
-
-#define NFSPROG ((u_long) 100003)
-#define MOUNTPROG ((u_long) 100005)
-#define YPXPROG ((u_long) 100069)
-#define YPPROG ((u_long) 100004)
-#define YPPROC_DOMAIN_NONACK ((u_long) 2)
-#define MOUNTPROC_MNT ((u_long) 1)
-
-static void logit __P((int, struct sockaddr_in *, u_long, u_long, const char *));
-static void toggle_verboselog __P((int));
-
-int verboselog = 0;
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_WARNING;
-
-/* A handful of macros for "readability". */
-
-#define good_client(a) hosts_ctl("portmap", "", inet_ntoa(a->sin_addr), "")
-
-#define legal_port(a,p) \
- (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
-
-#define log_bad_port(addr, proc, prog) \
- logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
-
-#define log_bad_host(addr, proc, prog) \
- logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
-
-#define log_bad_owner(addr, proc, prog) \
- logit(deny_severity, addr, proc, prog, ": request from non-local host")
-
-#define log_no_forward(addr, proc, prog) \
- logit(deny_severity, addr, proc, prog, ": request not forwarded")
-
-#define log_client(addr, proc, prog) \
- logit(allow_severity, addr, proc, prog, "")
-
-/* check_startup - additional startup code */
-
-void
-check_startup()
-{
-
- /*
- * Give up root privileges so that we can never allocate a privileged
- * port when forwarding an rpc request.
- */
- if (setuid(1) == -1) {
- syslog(LOG_ERR, "setuid(1) failed: %m");
- exit(1);
- }
- (void) signal(SIGINT, toggle_verboselog);
-}
-
-/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
-
-int
-check_default(addr, proc, prog)
- struct sockaddr_in *addr;
- u_long proc, prog;
-{
-#ifdef HOSTS_ACCESS
- if (!(from_local(addr) || good_client(addr))) {
- log_bad_host(addr, proc, prog);
- return (FALSE);
- }
-#endif
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
-}
-
-/* check_privileged_port - additional checks for privileged-port updates */
-
-int
-check_privileged_port(addr, proc, prog, port)
- struct sockaddr_in *addr;
- u_long proc, prog, port;
-{
-#ifdef CHECK_PORT
- if (!legal_port(addr, port)) {
- log_bad_port(addr, proc, prog);
- return (FALSE);
- }
-#endif
- return (TRUE);
-}
-
-/* check_setunset - additional checks for update requests */
-
-int
-check_setunset(addr, proc, prog, port)
- struct sockaddr_in *addr;
- u_long proc, prog, port;
-{
- if (!from_local(addr)) {
-#ifdef HOSTS_ACCESS
- (void) good_client(addr); /* because of side effects */
-#endif
- log_bad_owner(addr, proc, prog);
- return (FALSE);
- }
- if (port && !check_privileged_port(addr, proc, prog, port))
- return (FALSE);
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
-}
-
-/* check_callit - additional checks for forwarded requests */
-
-int
-check_callit(addr, proc, prog, aproc)
- struct sockaddr_in *addr;
- u_long proc, prog, aproc;
-{
-#ifdef HOSTS_ACCESS
- if (!(from_local(addr) || good_client(addr))) {
- log_bad_host(addr, proc, prog);
- return (FALSE);
- }
-#endif
- if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
- (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
- (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
- log_no_forward(addr, proc, prog);
- return (FALSE);
- }
- if (verboselog)
- log_client(addr, proc, prog);
- return (TRUE);
-}
-
-/* toggle_verboselog - toggle verbose logging flag */
-
-static void
-toggle_verboselog(sig)
- int sig;
-{
- (void) signal(sig, toggle_verboselog);
- verboselog = !verboselog;
-}
-
-/* logit - report events of interest via the syslog daemon */
-
-static void
-logit(severity, addr, procnum, prognum, text)
- int severity;
- struct sockaddr_in *addr;
- u_long procnum, prognum;
- const char *text;
-{
- const char *procname;
- char procbuf[4 * sizeof(u_long)];
- const char *progname;
- char progbuf[4 * sizeof(u_long)];
- struct rpcent *rpc;
- struct proc_map {
- u_long code;
- const char *proc;
- };
- struct proc_map *procp;
- static struct proc_map procmap[] = {
- {PMAPPROC_CALLIT, "callit"},
- {PMAPPROC_DUMP, "dump"},
- {PMAPPROC_GETPORT, "getport"},
- {PMAPPROC_NULL, "null"},
- {PMAPPROC_SET, "set"},
- {PMAPPROC_UNSET, "unset"},
- {0, 0},
- };
-
- /*
- * Fork off a process or the portmap daemon might hang while
- * getrpcbynumber() or syslog() does its thing.
- */
-
- if (fork() == 0) {
-
- /* Try to map program number to name. */
-
- if (prognum == 0) {
- progname = "";
- } else if ((rpc = getrpcbynumber((int) prognum))) {
- progname = rpc->r_name;
- } else {
- sprintf(progbuf, "%lu", prognum);
- progname = progbuf;
- }
-
- /* Try to map procedure number to name. */
-
- for (procp = procmap; procp->proc && procp->code != procnum; procp++)
- /* void */ ;
- if ((procname = procp->proc) == 0) {
- sprintf(procbuf, "%lu", (u_long) procnum);
- procname = procbuf;
- }
-
- /* Write syslog record. */
-
- syslog(severity, "connect from %s to %s(%s)%s",
- inet_ntoa(addr->sin_addr), procname, progname, text);
- exit(0);
- }
-}
diff --git a/usr.sbin/portmap/pmap_dump/Makefile b/usr.sbin/portmap/pmap_dump/Makefile
deleted file mode 100644
index 0064f28630d1..000000000000
--- a/usr.sbin/portmap/pmap_dump/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
-
-PROG= pmap_dump
-NOMAN= noman
-
-.include "${.CURDIR}/../../Makefile.inc"
-.include <bsd.prog.mk>
diff --git a/usr.sbin/portmap/pmap_dump/pmap_dump.c b/usr.sbin/portmap/pmap_dump/pmap_dump.c
deleted file mode 100644
index 96fb5c2edb99..000000000000
--- a/usr.sbin/portmap/pmap_dump/pmap_dump.c
+++ /dev/null
@@ -1,69 +0,0 @@
- /*
- * pmap_dump - dump portmapper table in format readable by pmap_set
- *
- * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
- * Computing Science, Eindhoven University of Technology, The Netherlands.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#) pmap_dump.c 1.1 92/06/11 22:53:15";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef SYSV40
-#include <netinet/in.h>
-#include <rpc/rpcent.h>
-#else
-#include <netdb.h>
-#endif
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <rpc/pmap_prot.h>
-
-static const char *protoname __P((u_long));
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- struct sockaddr_in addr;
- register struct pmaplist *list;
- register struct rpcent *rpc;
-
- get_myaddress(&addr);
-
- for (list = pmap_getmaps(&addr); list; list = list->pml_next) {
- rpc = getrpcbynumber((int) list->pml_map.pm_prog);
- printf("%10lu %4lu %5s %6lu %s\n",
- list->pml_map.pm_prog,
- list->pml_map.pm_vers,
- protoname(list->pml_map.pm_prot),
- list->pml_map.pm_port,
- rpc ? rpc->r_name : "");
- }
-#undef perror
- return (fclose(stdout) ? (perror(argv[0]), 1) : 0);
-}
-
-static const char *
-protoname(proto)
- u_long proto;
-{
- static char buf[BUFSIZ];
-
- switch (proto) {
- case IPPROTO_UDP:
- return ("udp");
- case IPPROTO_TCP:
- return ("tcp");
- default:
- sprintf(buf, "%lu", proto);
- return (buf);
- }
-}
diff --git a/usr.sbin/portmap/pmap_set/Makefile b/usr.sbin/portmap/pmap_set/Makefile
deleted file mode 100644
index 987e3209d303..000000000000
--- a/usr.sbin/portmap/pmap_set/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
-
-PROG= pmap_set
-NOMAN= noman
-
-.include "${.CURDIR}/../../Makefile.inc"
-.include <bsd.prog.mk>
diff --git a/usr.sbin/portmap/pmap_set/pmap_set.c b/usr.sbin/portmap/pmap_set/pmap_set.c
deleted file mode 100644
index 35a7fbe6e591..000000000000
--- a/usr.sbin/portmap/pmap_set/pmap_set.c
+++ /dev/null
@@ -1,78 +0,0 @@
- /*
- * pmap_set - set portmapper table from data produced by pmap_dump
- *
- * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
- * Computing Science, Eindhoven University of Technology, The Netherlands.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#) pmap_set.c 1.1 92/06/11 22:53:16";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#include <err.h>
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef SYSV40
-#include <netinet/in.h>
-#endif
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-
-static int parse_line __P((char *, u_long *, u_long *, int *, unsigned *));
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- struct sockaddr_in addr;
- char buf[BUFSIZ];
- u_long prog;
- u_long vers;
- int prot;
- unsigned port;
-
- get_myaddress(&addr);
-
- while (fgets(buf, sizeof(buf), stdin)) {
- if (parse_line(buf, &prog, &vers, &prot, &port) == 0) {
- warnx("malformed line: %s", buf);
- return (1);
- }
- if (pmap_set(prog, vers, prot, (unsigned short) port) == 0)
- warnx("not registered: %s", buf);
- }
- return (0);
-}
-
-/* parse_line - convert line to numbers */
-
-static int
-parse_line(buf, prog, vers, prot, port)
- char *buf;
- u_long *prog, *vers;
- int *prot;
- unsigned *port;
-{
- char proto_name[BUFSIZ];
-
- if (sscanf(buf, "%lu %lu %s %u", prog, vers, proto_name, port) != 4) {
- return (0);
- }
- if (strcmp(proto_name, "tcp") == 0) {
- *prot = IPPROTO_TCP;
- return (1);
- }
- if (strcmp(proto_name, "udp") == 0) {
- *prot = IPPROTO_UDP;
- return (1);
- }
- if (sscanf(proto_name, "%d", prot) == 1) {
- return (1);
- }
- return (0);
-}
diff --git a/usr.sbin/portmap/portmap.8 b/usr.sbin/portmap/portmap.8
deleted file mode 100644
index 455ccbd80354..000000000000
--- a/usr.sbin/portmap/portmap.8
+++ /dev/null
@@ -1,122 +0,0 @@
-.\" Copyright (c) 1987 Sun Microsystems
-.\" Copyright (c) 1990, 1991, 1993
-.\" The Regents of the University of California. 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 the University of
-.\" California, Berkeley and its contributors.
-.\" 4. 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 BY THE REGENTS 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 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.
-.\"
-.\" @(#)portmap.8 8.1 (Berkeley) 6/6/93
-.\" $FreeBSD$
-.\"
-.Dd June 6, 1993
-.Dt PORTMAP 8
-.Os BSD 4.3
-.Sh NAME
-.Nm portmap
-.Nd
-.Tn RPC
-program,version
-to
-.Tn DARPA
-port mapper
-.Sh SYNOPSIS
-.Nm
-.Op Fl d
-.Op Fl v
-.Sh DESCRIPTION
-.Nm Portmap
-is a server that converts
-.Tn RPC
-program numbers into
-.Tn DARPA
-protocol port numbers.
-It must be running in order to make
-.Tn RPC
-calls.
-.Pp
-When an
-.Tn RPC
-server is started, it will tell
-.Nm
-what port number it is listening to, and what
-.Tn RPC
-program numbers it is prepared to serve.
-When a client wishes to make an
-.Tn RPC
-call to a given program number,
-it will first contact
-.Nm
-on the server machine to determine
-the port number where
-.Tn RPC
-packets should be sent.
-.Pp
-.Nm Portmap
-must be started before any
-.Tn RPC
-servers are invoked.
-.Pp
-.Nm Portmap
-uses
-.Xr hosts_access 5
-access control by default.
-Access control patterns may only reference IP addresses.
-.Pp
-Normally
-.Nm
-forks and dissociates itself from the terminal
-like any other daemon.
-.Nm Portmap
-then logs errors using
-.Xr syslog 3 .
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl d
-Prevent
-.Nm
-from running as a daemon,
-and causes errors and debugging information
-to be printed to the standard error output.
-.It Fl v
-Enable verbose logging of access control checks.
-.El
-.Sh SEE ALSO
-.Xr hosts_access 5 ,
-.Xr inetd.conf 5 ,
-.Xr inetd 8 ,
-.Xr rpcinfo 8
-.Sh BUGS
-If
-.Nm
-crashes, all servers must be restarted.
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.3
diff --git a/usr.sbin/portmap/portmap.c b/usr.sbin/portmap/portmap.c
deleted file mode 100644
index 658b53cbf872..000000000000
--- a/usr.sbin/portmap/portmap.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. 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 the University of
- * California, Berkeley and its contributors.
- * 4. 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 BY THE REGENTS 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 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.
- */
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)portmap.c 8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-/*
-@(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
-static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
-*/
-
-/*
- * portmap.c, Implements the program,version to port number mapping for
- * rpc.
- */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#include <err.h>
-#include <errno.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/signal.h>
-#include <sys/resource.h>
-
-#include "pmap_check.h"
-
-static void reg_service __P((struct svc_req *, SVCXPRT *));
-static void reap __P((int));
-static void callit __P((struct svc_req *, SVCXPRT *));
-static void usage __P((void));
-
-struct pmaplist *pmaplist;
-int debugging = 0;
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- SVCXPRT *xprt;
- int sock, c;
- struct sockaddr_in addr;
- int len = sizeof(struct sockaddr_in);
- register struct pmaplist *pml;
-
- while ((c = getopt(argc, argv, "dv")) != -1) {
- switch (c) {
-
- case 'd':
- debugging = 1;
- break;
-
- case 'v':
- verboselog = 1;
- break;
-
- default:
- usage();
- }
- }
-
- if (!debugging && daemon(0, 0))
- err(1, "fork");
-
- openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
- LOG_DAEMON);
-
- if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- syslog(LOG_ERR, "cannot create udp socket: %m");
- exit(1);
- }
-
- addr.sin_addr.s_addr = 0;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PMAPPORT);
- if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
- syslog(LOG_ERR, "cannot bind udp: %m");
- exit(1);
- }
-
- if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
- syslog(LOG_ERR, "couldn't do udp_create");
- exit(1);
- }
- /* make an entry for ourself */
- pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
- pml->pml_next = 0;
- pml->pml_map.pm_prog = PMAPPROG;
- pml->pml_map.pm_vers = PMAPVERS;
- pml->pml_map.pm_prot = IPPROTO_UDP;
- pml->pml_map.pm_port = PMAPPORT;
- pmaplist = pml;
-
- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- syslog(LOG_ERR, "cannot create tcp socket: %m");
- exit(1);
- }
- if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
- syslog(LOG_ERR, "cannot bind tcp: %m");
- exit(1);
- }
- if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
- == (SVCXPRT *)NULL) {
- syslog(LOG_ERR, "couldn't do tcp_create");
- exit(1);
- }
- /* make an entry for ourself */
- pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
- pml->pml_map.pm_prog = PMAPPROG;
- pml->pml_map.pm_vers = PMAPVERS;
- pml->pml_map.pm_prot = IPPROTO_TCP;
- pml->pml_map.pm_port = PMAPPORT;
- pml->pml_next = pmaplist;
- pmaplist = pml;
-
- (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
-
- /* additional initializations */
- check_startup();
- (void)signal(SIGCHLD, reap);
- svc_run();
- syslog(LOG_ERR, "svc_run returned unexpectedly");
- abort();
-}
-
-static void
-usage()
-{
- fprintf(stderr, "usage: portmap [-dv]\n");
- exit(1);
-}
-
-#ifndef lint
-/* need to override perror calls in rpc library */
-void
-perror(what)
- const char *what;
-{
- syslog(LOG_ERR, "%s: %m", what);
-}
-#endif
-
-static struct pmaplist *
-find_service(prog, vers, prot)
- u_long prog, vers, prot;
-{
- register struct pmaplist *hit = NULL;
- register struct pmaplist *pml;
-
- for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
- if ((pml->pml_map.pm_prog != prog) ||
- (pml->pml_map.pm_prot != prot))
- continue;
- hit = pml;
- if (pml->pml_map.pm_vers == vers)
- break;
- }
- return (hit);
-}
-
-/*
- * 1 OK, 0 not
- */
-static void
-reg_service(rqstp, xprt)
- struct svc_req *rqstp;
- SVCXPRT *xprt;
-{
- struct pmap reg;
- struct pmaplist *pml, *prevpml, *fnd;
- int ans, port;
- caddr_t t;
-
- /*
- * Later wrappers change the logging severity on the fly. Reset to
- * defaults before handling the next request.
- */
- allow_severity = LOG_INFO;
- deny_severity = LOG_WARNING;
-
- if (debugging)
- (void) fprintf(stderr, "server: about to do a switch\n");
- switch (rqstp->rq_proc) {
-
- case PMAPPROC_NULL:
- /*
- * Null proc call
- */
- /* remote host authorization check */
- check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
- if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
- abort();
- }
- break;
-
- case PMAPPROC_SET:
- /*
- * Set a program,version to port mapping
- */
- if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
- svcerr_decode(xprt);
- else {
- /* reject non-local requests, protect priv. ports */
- if (!check_setunset(svc_getcaller(xprt),
- rqstp->rq_proc, reg.pm_prog, reg.pm_port)) {
- ans = 0;
- goto done;
- }
- /*
- * check to see if already used
- * find_service returns a hit even if
- * the versions don't match, so check for it
- */
- fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
- if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
- if (fnd->pml_map.pm_port == reg.pm_port) {
- ans = 1;
- goto done;
- }
- else {
- ans = 0;
- goto done;
- }
- } else {
- /*
- * add to END of list
- */
- pml = (struct pmaplist *)
- malloc((u_int)sizeof(struct pmaplist));
- pml->pml_map = reg;
- pml->pml_next = 0;
- if (pmaplist == 0) {
- pmaplist = pml;
- } else {
- for (fnd= pmaplist; fnd->pml_next != 0;
- fnd = fnd->pml_next);
- fnd->pml_next = pml;
- }
- ans = 1;
- }
- done:
- if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
- debugging) {
- (void) fprintf(stderr, "svc_sendreply\n");
- abort();
- }
- }
- break;
-
- case PMAPPROC_UNSET:
- /*
- * Remove a program,version to port mapping.
- */
- if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
- svcerr_decode(xprt);
- else {
- ans = 0;
- /* reject non-local requests */
- if (!check_setunset(svc_getcaller(xprt),
- rqstp->rq_proc, reg.pm_prog, (u_long) 0))
- goto done;
- for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
- if ((pml->pml_map.pm_prog != reg.pm_prog) ||
- (pml->pml_map.pm_vers != reg.pm_vers)) {
- /* both pml & prevpml move forwards */
- prevpml = pml;
- pml = pml->pml_next;
- continue;
- }
- /* found it; pml moves forward, prevpml stays */
- /* privileged port check */
- if (!check_privileged_port(svc_getcaller(xprt),
- rqstp->rq_proc,
- reg.pm_prog,
- pml->pml_map.pm_port)) {
- ans = 0;
- break;
- }
- ans = 1;
- t = (caddr_t)pml;
- pml = pml->pml_next;
- if (prevpml == NULL)
- pmaplist = pml;
- else
- prevpml->pml_next = pml;
- free(t);
- }
- if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
- debugging) {
- (void) fprintf(stderr, "svc_sendreply\n");
- abort();
- }
- }
- break;
-
- case PMAPPROC_GETPORT:
- /*
- * Lookup the mapping for a program,version and return its port
- */
- if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
- svcerr_decode(xprt);
- else {
- /* remote host authorization check */
- if (!check_default(svc_getcaller(xprt),
- rqstp->rq_proc,
- reg.pm_prog)) {
- ans = 0;
- goto done;
- }
- fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
- if (fnd)
- port = fnd->pml_map.pm_port;
- else
- port = 0;
- if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
- debugging) {
- (void) fprintf(stderr, "svc_sendreply\n");
- abort();
- }
- }
- break;
-
- case PMAPPROC_DUMP:
- /*
- * Return the current set of mapped program,version
- */
- if (!svc_getargs(xprt, xdr_void, NULL))
- svcerr_decode(xprt);
- else {
- /* remote host authorization check */
- struct pmaplist *p;
- if (!check_default(svc_getcaller(xprt),
- rqstp->rq_proc, (u_long) 0)) {
- p = 0; /* send empty list */
- } else {
- p = pmaplist;
- }
- if ((!svc_sendreply(xprt, xdr_pmaplist,
- (caddr_t)&p)) && debugging) {
- (void) fprintf(stderr, "svc_sendreply\n");
- abort();
- }
- }
- break;
-
- case PMAPPROC_CALLIT:
- /*
- * Calls a procedure on the local machine. If the requested
- * procedure is not registered this procedure does not return
- * error information!!
- * This procedure is only supported on rpc/udp and calls via
- * rpc/udp. It passes null authentication parameters.
- */
- callit(rqstp, xprt);
- break;
-
- default:
- /* remote host authorization check */
- check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
- svcerr_noproc(xprt);
- break;
- }
-}
-
-
-/*
- * Stuff for the rmtcall service
- */
-#define ARGSIZE 9000
-
-struct encap_parms {
- u_int arglen;
- char *args;
-};
-
-static bool_t
-xdr_encap_parms(xdrs, epp)
- XDR *xdrs;
- struct encap_parms *epp;
-{
-
- return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
-}
-
-struct rmtcallargs {
- u_long rmt_prog;
- u_long rmt_vers;
- u_long rmt_port;
- u_long rmt_proc;
- struct encap_parms rmt_args;
-};
-
-static bool_t
-xdr_rmtcall_args(xdrs, cap)
- XDR *xdrs;
- struct rmtcallargs *cap;
-{
-
- /* does not get a port number */
- if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
- xdr_u_long(xdrs, &(cap->rmt_vers)) &&
- xdr_u_long(xdrs, &(cap->rmt_proc))) {
- return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
- }
- return (FALSE);
-}
-
-static bool_t
-xdr_rmtcall_result(xdrs, cap)
- XDR *xdrs;
- struct rmtcallargs *cap;
-{
- if (xdr_u_long(xdrs, &(cap->rmt_port)))
- return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
- return (FALSE);
-}
-
-/*
- * only worries about the struct encap_parms part of struct rmtcallargs.
- * The arglen must already be set!!
- */
-static bool_t
-xdr_opaque_parms(xdrs, cap)
- XDR *xdrs;
- struct rmtcallargs *cap;
-{
- return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
-}
-
-/*
- * This routine finds and sets the length of incoming opaque paraters
- * and then calls xdr_opaque_parms.
- */
-static bool_t
-xdr_len_opaque_parms(xdrs, cap)
- XDR *xdrs;
- struct rmtcallargs *cap;
-{
- register u_int beginpos, lowpos, highpos, currpos, pos;
-
- beginpos = lowpos = pos = xdr_getpos(xdrs);
- highpos = lowpos + ARGSIZE;
- while ((int)(highpos - lowpos) >= 0) {
- currpos = (lowpos + highpos) / 2;
- if (xdr_setpos(xdrs, currpos)) {
- pos = currpos;
- lowpos = currpos + 1;
- } else {
- highpos = currpos - 1;
- }
- }
- xdr_setpos(xdrs, beginpos);
- cap->rmt_args.arglen = pos - beginpos;
- return (xdr_opaque_parms(xdrs, cap));
-}
-
-/*
- * Call a remote procedure service
- * This procedure is very quiet when things go wrong.
- * The proc is written to support broadcast rpc. In the broadcast case,
- * a machine should shut-up instead of complain, less the requestor be
- * overrun with complaints at the expense of not hearing a valid reply ...
- *
- * This now forks so that the program & process that it calls can call
- * back to the portmapper.
- */
-static void
-callit(rqstp, xprt)
- struct svc_req *rqstp;
- SVCXPRT *xprt;
-{
- struct rmtcallargs a;
- struct pmaplist *pml;
- u_short port;
- struct sockaddr_in me;
- int pid, so = -1;
- CLIENT *client;
- struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
- struct timeval timeout;
- char buf[ARGSIZE];
-
- timeout.tv_sec = 5;
- timeout.tv_usec = 0;
- a.rmt_args.args = buf;
- if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a))
- return;
- /* host and service access control */
- if (!check_callit(svc_getcaller(xprt),
- rqstp->rq_proc, a.rmt_prog, a.rmt_proc))
- return;
- if ((pml = find_service(a.rmt_prog, a.rmt_vers,
- (u_long)IPPROTO_UDP)) == NULL)
- return;
- /*
- * fork a child to do the work. Parent immediately returns.
- * Child exits upon completion.
- */
- if ((pid = fork()) != 0) {
- if (pid < 0)
- syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
- a.rmt_prog);
- return;
- }
- port = pml->pml_map.pm_port;
- get_myaddress(&me);
- me.sin_port = htons(port);
- client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
- if (client != (CLIENT *)NULL) {
- if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
- client->cl_auth = authunix_create(au->aup_machname,
- au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
- }
- a.rmt_port = (u_long)port;
- if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
- xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
- svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
- }
- AUTH_DESTROY(client->cl_auth);
- clnt_destroy(client);
- }
- (void)close(so);
- exit(0);
-}
-
-static void
-reap(sig)
- int sig;
-{
- int save_errno;
-
- save_errno = errno;
- while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
- errno = save_errno;
-}
diff --git a/usr.sbin/rpc.lockd/Makefile b/usr.sbin/rpc.lockd/Makefile
index 19a6565a4048..ba6b3c77dbc1 100644
--- a/usr.sbin/rpc.lockd/Makefile
+++ b/usr.sbin/rpc.lockd/Makefile
@@ -1,15 +1,17 @@
-# $FreeBSD$
+# $FreeBSD$
+# $NetBSD: Makefile,v 1.12 2000/08/07 16:23:31 thorpej Exp $
-PROG = rpc.lockd
-SRCS = nlm_prot_svc.c nlm_prot.h lockd.c procs.c
-MAN8 = rpc.lockd.8
+PROG= rpc.lockd
+SRCS= nlm_prot_svc.c lockd.c lock_proc.c lockd_lock.c
+MAN8= rpc.lockd.8
+MLINKS= rpc.lockd.8 lockd.8
-DPADD= ${LIBRPCSVC}
-LDADD= -lrpcsvc
+CFLAGS+= -I. -I${DESTDIR}/usr/include/rpcsvc
-CFLAGS+= -I.
+DPADD= ${LIBRPCSVC} ${LIBUTIL}
+LDADD= -lrpcsvc -lutil
-CLEANFILES= nlm_prot_svc.c nlm_prot.h
+CLEANFILES= nlm_prot_svc.c nlm_prot.h test
RPCSRC= ${DESTDIR}/usr/include/rpcsvc/nlm_prot.x
RPCGEN= rpcgen -L -C
@@ -20,7 +22,7 @@ nlm_prot_svc.c: ${RPCSRC}
nlm_prot.h: ${RPCSRC}
${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
-test: test.c
- cc -o test test.c -lrpcsvc
+test: ${.CURDIR}/test.c
+ cc -o test ${.CURDIR}/test.c -lrpcsvc
.include <bsd.prog.mk>
diff --git a/usr.sbin/rpc.lockd/lock_proc.c b/usr.sbin/rpc.lockd/lock_proc.c
new file mode 100644
index 000000000000..8b08fd0f49eb
--- /dev/null
+++ b/usr.sbin/rpc.lockd/lock_proc.c
@@ -0,0 +1,1294 @@
+/* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 1995
+ * A.R. Gordon (andrew.gordon@net-tel.co.uk). 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 for the FreeBSD project
+ * 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 ANDREW GORDON 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>
+#ifndef lint
+__RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $");
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <netconfig.h>
+
+#include <rpc/rpc.h>
+#include <rpcsvc/sm_inter.h>
+
+#include "lockd.h"
+#include <rpcsvc/nlm_prot.h>
+#include "lockd_lock.h"
+
+
+#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
+#define CLIENT_CACHE_LIFETIME 120 /* In seconds */
+
+static void log_from_addr __P((char *, struct svc_req *));
+static int addrcmp __P((struct sockaddr *, struct sockaddr *));
+
+/* log_from_addr ----------------------------------------------------------- */
+/*
+ * Purpose: Log name of function called and source address
+ * Returns: Nothing
+ * Notes: Extracts the source address from the transport handle
+ * passed in as part of the called procedure specification
+ */
+static void
+log_from_addr(fun_name, req)
+ char *fun_name;
+ struct svc_req *req;
+{
+ struct sockaddr *addr;
+ char hostname_buf[NI_MAXHOST];
+
+ addr = svc_getrpccaller(req->rq_xprt)->buf;
+ if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
+ NULL, 0, 0) != 0)
+ return;
+
+ syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
+}
+
+/* get_client -------------------------------------------------------------- */
+/*
+ * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
+ * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
+ * Notes: Creating a CLIENT* is quite expensive, involving a
+ * conversation with the remote portmapper to get the
+ * port number. Since a given client is quite likely
+ * to make several locking requests in succession, it is
+ * desirable to cache the created CLIENT*.
+ *
+ * Since we are using UDP rather than TCP, there is no cost
+ * to the remote system in keeping these cached indefinitely.
+ * Unfortunately there is a snag: if the remote system
+ * reboots, the cached portmapper results will be invalid,
+ * and we will never detect this since all of the xxx_msg()
+ * calls return no result - we just fire off a udp packet
+ * and hope for the best.
+ *
+ * We solve this by discarding cached values after two
+ * minutes, regardless of whether they have been used
+ * in the meanwhile (since a bad one might have been used
+ * plenty of times, as the host keeps retrying the request
+ * and we keep sending the reply back to the wrong port).
+ *
+ * Given that the entries will always expire in the order
+ * that they were created, there is no point in a LRU
+ * algorithm for when the cache gets full - entries are
+ * always re-used in sequence.
+ */
+static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
+static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
+static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
+static int clnt_cache_next_to_use = 0;
+
+static int
+addrcmp(sa1, sa2)
+ struct sockaddr *sa1;
+ struct sockaddr *sa2;
+{
+ int len;
+ void *p1, *p2;
+
+ if (sa1->sa_family != sa2->sa_family)
+ return -1;
+
+ switch (sa1->sa_family) {
+ case AF_INET:
+ p1 = &((struct sockaddr_in *)sa1)->sin_addr;
+ p2 = &((struct sockaddr_in *)sa2)->sin_addr;
+ len = 4;
+ break;
+ case AF_INET6:
+ p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
+ p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
+ len = 16;
+ break;
+ default:
+ return -1;
+ }
+
+ return memcmp(p1, p2, len);
+}
+
+CLIENT *
+get_client(host_addr, vers)
+ struct sockaddr *host_addr;
+ rpcvers_t vers;
+{
+ CLIENT *client;
+ struct timeval retry_time, time_now;
+ int i;
+ char *netid;
+ struct netconfig *nconf;
+ char host[NI_MAXHOST];
+
+ gettimeofday(&time_now, NULL);
+
+ /*
+ * Search for the given client in the cache, zapping any expired
+ * entries that we happen to notice in passing.
+ */
+ for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
+ client = clnt_cache_ptr[i];
+ if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
+ < time_now.tv_sec)) {
+ /* Cache entry has expired. */
+ if (debug_level > 3)
+ syslog(LOG_DEBUG, "Expired CLIENT* in cache");
+ clnt_cache_time[i] = 0L;
+ clnt_destroy(client);
+ clnt_cache_ptr[i] = NULL;
+ client = NULL;
+ }
+ if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
+ host_addr)) {
+ /* Found it! */
+ if (debug_level > 3)
+ syslog(LOG_DEBUG, "Found CLIENT* in cache");
+ return (client);
+ }
+ }
+
+ /* Not found in cache. Free the next entry if it is in use. */
+ if (clnt_cache_ptr[clnt_cache_next_to_use]) {
+ clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
+ clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
+ }
+
+ /*
+ * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
+ * to avoid DNS lookups.
+ */
+ if (getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
+ NULL, 0, NI_NUMERICHOST) != 0) {
+ syslog(LOG_ERR, "unable to get name string for caller");
+ return NULL;
+ }
+
+#if 1
+ if (host_addr->sa_family == AF_INET6)
+ netid = "udp6";
+ else
+ netid = "udp";
+#else
+ if (host_addr->sa_family == AF_INET6)
+ netid = "tcp6";
+ else
+ netid = "tcp";
+#endif
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ syslog(LOG_ERR, "could not get netconfig info for '%s': "
+ "no /etc/netconfig file?", netid);
+ return NULL;
+ }
+
+ client = clnt_tp_create(host, NLM_PROG, vers, nconf);
+ freenetconfigent(nconf);
+
+ if (!client) {
+ syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
+ syslog(LOG_ERR, "Unable to return result to %s", host);
+ return NULL;
+ }
+
+ /* Success - update the cache entry */
+ clnt_cache_ptr[clnt_cache_next_to_use] = client;
+ memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
+ host_addr->sa_len);
+ clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
+ if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE)
+ clnt_cache_next_to_use = 0;
+
+ /*
+ * Disable the default timeout, so we can specify our own in calls
+ * to clnt_call(). (Note that the timeout is a different concept
+ * from the retry period set in clnt_udp_create() above.)
+ */
+ retry_time.tv_sec = -1;
+ retry_time.tv_usec = -1;
+ clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
+
+ if (debug_level > 3)
+ syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
+ return client;
+}
+
+
+/* transmit_result --------------------------------------------------------- */
+/*
+ * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
+ * Returns: Nothing - we have no idea if the datagram got there
+ * Notes: clnt_call() will always fail (with timeout) as we are
+ * calling it with timeout 0 as a hack to just issue a datagram
+ * without expecting a result
+ */
+void
+transmit_result(opcode, result, addr)
+ int opcode;
+ nlm_res *result;
+ struct sockaddr *addr;
+{
+ static char dummy;
+ CLIENT *cli;
+ struct timeval timeo;
+ int success;
+
+ if ((cli = get_client(addr, NLM_VERS)) != NULL) {
+ timeo.tv_sec = 0; /* No timeout - not expecting response */
+ timeo.tv_usec = 0;
+
+ success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
+ &dummy, timeo);
+
+ if (debug_level > 2)
+ syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
+ success, clnt_sperrno(success));
+ }
+}
+/* transmit4_result --------------------------------------------------------- */
+/*
+ * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
+ * Returns: Nothing - we have no idea if the datagram got there
+ * Notes: clnt_call() will always fail (with timeout) as we are
+ * calling it with timeout 0 as a hack to just issue a datagram
+ * without expecting a result
+ */
+void
+transmit4_result(opcode, result, addr)
+ int opcode;
+ nlm4_res *result;
+ struct sockaddr *addr;
+{
+ static char dummy;
+ CLIENT *cli;
+ struct timeval timeo;
+ int success;
+
+ if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
+ timeo.tv_sec = 0; /* No timeout - not expecting response */
+ timeo.tv_usec = 0;
+
+ success = clnt_call(cli, opcode, xdr_nlm4_res, result, xdr_void,
+ &dummy, timeo);
+
+ if (debug_level > 2)
+ syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
+ success, clnt_sperrno(success));
+ }
+}
+
+/*
+ * converts a struct nlm_lock to struct nlm4_lock
+ */
+static void nlmtonlm4 __P((struct nlm_lock *, struct nlm4_lock *));
+static void
+nlmtonlm4(arg, arg4)
+ struct nlm_lock *arg;
+ struct nlm4_lock *arg4;
+{
+ memcpy(arg4, arg, sizeof(nlm_lock));
+ arg4->l_offset = arg->l_offset;
+ arg4->l_len = arg->l_len;
+}
+/* ------------------------------------------------------------------------- */
+/*
+ * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
+ * involved to ensure reclaim of locks after a crash of the "stateless"
+ * server.
+ *
+ * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
+ * The first are standard RPCs with argument and result.
+ * The nlm_xxx_msg() calls implement exactly the same functions, but
+ * use two pseudo-RPCs (one in each direction). These calls are NOT
+ * standard use of the RPC protocol in that they do not return a result
+ * at all (NB. this is quite different from returning a void result).
+ * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
+ * datagrams, requiring higher-level code to perform retries.
+ *
+ * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
+ * are documented in the comments to get_client() above), this is the
+ * interface used by all current commercial NFS implementations
+ * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
+ * implementations to continue using the standard RPC libraries, while
+ * avoiding the block-until-result nature of the library interface.
+ *
+ * No client implementations have been identified so far that make use
+ * of the true RPC version (early SunOS releases would be a likely candidate
+ * for testing).
+ */
+
+/* nlm_test ---------------------------------------------------------------- */
+/*
+ * Purpose: Test whether a specified lock would be granted if requested
+ * Returns: nlm_granted (or error code)
+ * Notes:
+ */
+nlm_testres *
+nlm_test_1_svc(arg, rqstp)
+ nlm_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_testres res;
+ struct nlm4_lock arg4;
+ struct nlm4_holder *holder;
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_test", rqstp);
+
+ holder = testlock(&arg4, 0);
+ /*
+ * Copy the cookie from the argument into the result. Note that this
+ * is slightly hazardous, as the structure contains a pointer to a
+ * malloc()ed buffer that will get freed by the caller. However, the
+ * main function transmits the result before freeing the argument
+ * so it is in fact safe.
+ */
+ res.cookie = arg->cookie;
+ if (holder == NULL) {
+ res.stat.stat = nlm_granted;
+ } else {
+ res.stat.stat = nlm_denied;
+ memcpy(&res.stat.nlm_testrply_u.holder, holder,
+ sizeof(struct nlm_holder));
+ res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
+ res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
+ }
+ return (&res);
+}
+
+void *
+nlm_test_msg_1_svc(arg, rqstp)
+ nlm_testargs *arg;
+ struct svc_req *rqstp;
+{
+ nlm_testres res;
+ static char dummy;
+ struct sockaddr *addr;
+ CLIENT *cli;
+ int success;
+ struct timeval timeo;
+ struct nlm4_lock arg4;
+ struct nlm4_holder *holder;
+
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_test_msg", rqstp);
+
+ holder = testlock(&arg4, 0);
+
+ res.cookie = arg->cookie;
+ if (holder == NULL) {
+ res.stat.stat = nlm_granted;
+ } else {
+ res.stat.stat = nlm_denied;
+ memcpy(&res.stat.nlm_testrply_u.holder, holder,
+ sizeof(struct nlm_holder));
+ res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
+ res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
+ }
+
+ /*
+ * nlm_test has different result type to the other operations, so
+ * can't use transmit_result() in this case
+ */
+ addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
+ if ((cli = get_client(addr, NLM_VERS)) != NULL) {
+ timeo.tv_sec = 0; /* No timeout - not expecting response */
+ timeo.tv_usec = 0;
+
+ success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres,
+ &res, xdr_void, &dummy, timeo);
+
+ if (debug_level > 2)
+ syslog(LOG_DEBUG, "clnt_call returns %d", success);
+ }
+ return (NULL);
+}
+
+/* nlm_lock ---------------------------------------------------------------- */
+/*
+ * Purposes: Establish a lock
+ * Returns: granted, denied or blocked
+ * Notes: *** grace period support missing
+ */
+nlm_res *
+nlm_lock_1_svc(arg, rqstp)
+ nlm_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lockargs arg4;
+ nlmtonlm4(&arg->alock, &arg4.alock);
+ arg4.cookie = arg->cookie;
+ arg4.block = arg->block;
+ arg4.exclusive = arg->exclusive;
+ arg4.reclaim = arg->reclaim;
+ arg4.state = arg->state;
+
+ if (debug_level)
+ log_from_addr("nlm_lock", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+
+ res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
+ return (&res);
+}
+
+void *
+nlm_lock_msg_1_svc(arg, rqstp)
+ nlm_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lockargs arg4;
+
+ nlmtonlm4(&arg->alock, &arg4.alock);
+ arg4.cookie = arg->cookie;
+ arg4.block = arg->block;
+ arg4.exclusive = arg->exclusive;
+ arg4.reclaim = arg->reclaim;
+ arg4.state = arg->state;
+
+ if (debug_level)
+ log_from_addr("nlm_lock_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
+ transmit_result(NLM_LOCK_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+
+ return (NULL);
+}
+
+/* nlm_cancel -------------------------------------------------------------- */
+/*
+ * Purpose: Cancel a blocked lock request
+ * Returns: granted or denied
+ * Notes:
+ */
+nlm_res *
+nlm_cancel_1_svc(arg, rqstp)
+ nlm_cancargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lock arg4;
+
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_cancel", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+
+ /*
+ * Since at present we never return 'nlm_blocked', there can never be
+ * a lock to cancel, so this call always fails.
+ */
+ res.stat.stat = unlock(&arg4, LOCK_CANCEL);
+ return (&res);
+}
+
+void *
+nlm_cancel_msg_1_svc(arg, rqstp)
+ nlm_cancargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lock arg4;
+
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_cancel_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ /*
+ * Since at present we never return 'nlm_blocked', there can never be
+ * a lock to cancel, so this call always fails.
+ */
+ res.stat.stat = unlock(&arg4, LOCK_CANCEL);
+ transmit_result(NLM_CANCEL_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+ return (NULL);
+}
+
+/* nlm_unlock -------------------------------------------------------------- */
+/*
+ * Purpose: Release an existing lock
+ * Returns: Always granted, unless during grace period
+ * Notes: "no such lock" error condition is ignored, as the
+ * protocol uses unreliable UDP datagrams, and may well
+ * re-try an unlock that has already succeeded.
+ */
+nlm_res *
+nlm_unlock_1_svc(arg, rqstp)
+ nlm_unlockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lock arg4;
+
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_unlock", rqstp);
+
+ res.stat.stat = unlock(&arg4, 0);
+ res.cookie = arg->cookie;
+
+ return (&res);
+}
+
+void *
+nlm_unlock_msg_1_svc(arg, rqstp)
+ nlm_unlockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+ struct nlm4_lock arg4;
+
+ nlmtonlm4(&arg->alock, &arg4);
+
+ if (debug_level)
+ log_from_addr("nlm_unlock_msg", rqstp);
+
+ res.stat.stat = unlock(&arg4, 0);
+ res.cookie = arg->cookie;
+
+ transmit_result(NLM_UNLOCK_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+ return (NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Client-side pseudo-RPCs for results. Note that for the client there
+ * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
+ * version returns the results in the RPC result, and so the client
+ * does not normally receive incoming RPCs.
+ *
+ * The exception to this is nlm_granted(), which is genuinely an RPC
+ * call from the server to the client - a 'call-back' in normal procedure
+ * call terms.
+ */
+
+/* nlm_granted ------------------------------------------------------------- */
+/*
+ * Purpose: Receive notification that formerly blocked lock now granted
+ * Returns: always success ('granted')
+ * Notes:
+ */
+nlm_res *
+nlm_granted_1_svc(arg, rqstp)
+ nlm_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+
+ if (debug_level)
+ log_from_addr("nlm_granted", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+
+ res.stat.stat = nlm_granted;
+ return (&res);
+}
+
+void *
+nlm_granted_msg_1_svc(arg, rqstp)
+ nlm_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+
+ if (debug_level)
+ log_from_addr("nlm_granted_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat.stat = nlm_granted;
+ transmit_result(NLM_GRANTED_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+ return (NULL);
+}
+
+/* nlm_test_res ------------------------------------------------------------ */
+/*
+ * Purpose: Accept result from earlier nlm_test_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm_test_res_1_svc(arg, rqstp)
+ nlm_testres *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm_test_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_lock_res ------------------------------------------------------------ */
+/*
+ * Purpose: Accept result from earlier nlm_lock_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm_lock_res_1_svc(arg, rqstp)
+ nlm_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm_lock_res", rqstp);
+
+ return (NULL);
+}
+
+/* nlm_cancel_res ---------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_cancel_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm_cancel_res_1_svc(arg, rqstp)
+ nlm_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm_cancel_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_unlock_res ---------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_unlock_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm_unlock_res_1_svc(arg, rqstp)
+ nlm_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm_unlock_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_granted_res --------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_granted_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm_granted_res_1_svc(arg, rqstp)
+ nlm_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm_granted_res", rqstp);
+ return (NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Calls for PCNFS locking (aka non-monitored locking, no involvement
+ * of rpc.statd).
+ *
+ * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
+ */
+
+/* nlm_share --------------------------------------------------------------- */
+/*
+ * Purpose: Establish a DOS-style lock
+ * Returns: success or failure
+ * Notes: Blocking locks are not supported - client is expected
+ * to retry if required.
+ */
+nlm_shareres *
+nlm_share_3_svc(arg, rqstp)
+ nlm_shareargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_shareres res;
+
+ if (debug_level)
+ log_from_addr("nlm_share", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat = nlm_granted;
+ res.sequence = 1234356; /* X/Open says this field is ignored? */
+ return (&res);
+}
+
+/* nlm_unshare ------------------------------------------------------------ */
+/*
+ * Purpose: Release a DOS-style lock
+ * Returns: nlm_granted, unless in grace period
+ * Notes:
+ */
+nlm_shareres *
+nlm_unshare_3_svc(arg, rqstp)
+ nlm_shareargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_shareres res;
+
+ if (debug_level)
+ log_from_addr("nlm_unshare", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat = nlm_granted;
+ res.sequence = 1234356; /* X/Open says this field is ignored? */
+ return (&res);
+}
+
+/* nlm_nm_lock ------------------------------------------------------------ */
+/*
+ * Purpose: non-monitored version of nlm_lock()
+ * Returns: as for nlm_lock()
+ * Notes: These locks are in the same style as the standard nlm_lock,
+ * but the rpc.statd should not be called to establish a
+ * monitor for the client machine, since that machine is
+ * declared not to be running a rpc.statd, and so would not
+ * respond to the statd protocol.
+ */
+nlm_res *
+nlm_nm_lock_3_svc(arg, rqstp)
+ nlm_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm_res res;
+
+ if (debug_level)
+ log_from_addr("nlm_nm_lock", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+ res.stat.stat = nlm_granted;
+ return (&res);
+}
+
+/* nlm_free_all ------------------------------------------------------------ */
+/*
+ * Purpose: Release all locks held by a named client
+ * Returns: Nothing
+ * Notes: Potential denial of service security problem here - the
+ * locks to be released are specified by a host name, independent
+ * of the address from which the request has arrived.
+ * Should probably be rejected if the named host has been
+ * using monitored locks.
+ */
+void *
+nlm_free_all_3_svc(arg, rqstp)
+ nlm_notify *arg;
+ struct svc_req *rqstp;
+{
+ static char dummy;
+
+ if (debug_level)
+ log_from_addr("nlm_free_all", rqstp);
+ return (&dummy);
+}
+
+/* calls for nlm version 4 (NFSv3) */
+/* nlm_test ---------------------------------------------------------------- */
+/*
+ * Purpose: Test whether a specified lock would be granted if requested
+ * Returns: nlm_granted (or error code)
+ * Notes:
+ */
+nlm4_testres *
+nlm4_test_4_svc(arg, rqstp)
+ nlm4_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_testres res;
+ struct nlm4_holder *holder;
+
+ if (debug_level)
+ log_from_addr("nlm4_test", rqstp);
+
+ holder = testlock(&arg->alock, LOCK_V4);
+
+ /*
+ * Copy the cookie from the argument into the result. Note that this
+ * is slightly hazardous, as the structure contains a pointer to a
+ * malloc()ed buffer that will get freed by the caller. However, the
+ * main function transmits the result before freeing the argument
+ * so it is in fact safe.
+ */
+ res.cookie = arg->cookie;
+ if (holder == NULL) {
+ res.stat.stat = nlm4_granted;
+ } else {
+ res.stat.stat = nlm4_denied;
+ memcpy(&res.stat.nlm4_testrply_u.holder, holder,
+ sizeof(struct nlm4_holder));
+ }
+ return (&res);
+}
+
+void *
+nlm4_test_msg_4_svc(arg, rqstp)
+ nlm4_testargs *arg;
+ struct svc_req *rqstp;
+{
+ nlm4_testres res;
+ static char dummy;
+ struct sockaddr *addr;
+ CLIENT *cli;
+ int success;
+ struct timeval timeo;
+ struct nlm4_holder *holder;
+
+ if (debug_level)
+ log_from_addr("nlm4_test_msg", rqstp);
+
+ holder = testlock(&arg->alock, LOCK_V4);
+
+ res.cookie = arg->cookie;
+ if (holder == NULL) {
+ res.stat.stat = nlm4_granted;
+ } else {
+ res.stat.stat = nlm4_denied;
+ memcpy(&res.stat.nlm4_testrply_u.holder, holder,
+ sizeof(struct nlm4_holder));
+ }
+
+ /*
+ * nlm_test has different result type to the other operations, so
+ * can't use transmit4_result() in this case
+ */
+ addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
+ if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
+ timeo.tv_sec = 0; /* No timeout - not expecting response */
+ timeo.tv_usec = 0;
+
+ success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres,
+ &res, xdr_void, &dummy, timeo);
+
+ if (debug_level > 2)
+ syslog(LOG_DEBUG, "clnt_call returns %d", success);
+ }
+ return (NULL);
+}
+
+/* nlm_lock ---------------------------------------------------------------- */
+/*
+ * Purposes: Establish a lock
+ * Returns: granted, denied or blocked
+ * Notes: *** grace period support missing
+ */
+nlm4_res *
+nlm4_lock_4_svc(arg, rqstp)
+ nlm4_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_lock", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_4() */
+ res.cookie = arg->cookie;
+
+ res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
+ return (&res);
+}
+
+void *
+nlm4_lock_msg_4_svc(arg, rqstp)
+ nlm4_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_lock_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
+ transmit4_result(NLM4_LOCK_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+
+ return (NULL);
+}
+
+/* nlm_cancel -------------------------------------------------------------- */
+/*
+ * Purpose: Cancel a blocked lock request
+ * Returns: granted or denied
+ * Notes:
+ */
+nlm4_res *
+nlm4_cancel_4_svc(arg, rqstp)
+ nlm4_cancargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_cancel", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+
+ /*
+ * Since at present we never return 'nlm_blocked', there can never be
+ * a lock to cancel, so this call always fails.
+ */
+ res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
+ return (&res);
+}
+
+void *
+nlm4_cancel_msg_4_svc(arg, rqstp)
+ nlm4_cancargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_cancel_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ /*
+ * Since at present we never return 'nlm_blocked', there can never be
+ * a lock to cancel, so this call always fails.
+ */
+ res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
+ transmit4_result(NLM4_CANCEL_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+ return (NULL);
+}
+
+/* nlm_unlock -------------------------------------------------------------- */
+/*
+ * Purpose: Release an existing lock
+ * Returns: Always granted, unless during grace period
+ * Notes: "no such lock" error condition is ignored, as the
+ * protocol uses unreliable UDP datagrams, and may well
+ * re-try an unlock that has already succeeded.
+ */
+nlm4_res *
+nlm4_unlock_4_svc(arg, rqstp)
+ nlm4_unlockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_unlock", rqstp);
+
+ res.stat.stat = unlock(&arg->alock, LOCK_V4);
+ res.cookie = arg->cookie;
+
+ return (&res);
+}
+
+void *
+nlm4_unlock_msg_4_svc(arg, rqstp)
+ nlm4_unlockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_unlock_msg", rqstp);
+
+ res.stat.stat = unlock(&arg->alock, LOCK_V4);
+ res.cookie = arg->cookie;
+
+ transmit4_result(NLM4_UNLOCK_RES, &res,
+ (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
+ return (NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Client-side pseudo-RPCs for results. Note that for the client there
+ * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
+ * version returns the results in the RPC result, and so the client
+ * does not normally receive incoming RPCs.
+ *
+ * The exception to this is nlm_granted(), which is genuinely an RPC
+ * call from the server to the client - a 'call-back' in normal procedure
+ * call terms.
+ */
+
+/* nlm_granted ------------------------------------------------------------- */
+/*
+ * Purpose: Receive notification that formerly blocked lock now granted
+ * Returns: always success ('granted')
+ * Notes:
+ */
+nlm4_res *
+nlm4_granted_4_svc(arg, rqstp)
+ nlm4_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_granted", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm_test_1() */
+ res.cookie = arg->cookie;
+
+ res.stat.stat = nlm4_granted;
+ return (&res);
+}
+
+void *
+nlm4_granted_msg_4_svc(arg, rqstp)
+ nlm4_testargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_granted_msg", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat.stat = nlm4_granted;
+ transmit4_result(NLM4_GRANTED_RES, &res,
+ (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
+ return (NULL);
+}
+
+/* nlm_test_res ------------------------------------------------------------ */
+/*
+ * Purpose: Accept result from earlier nlm_test_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm4_test_res_4_svc(arg, rqstp)
+ nlm4_testres *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm4_test_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_lock_res ------------------------------------------------------------ */
+/*
+ * Purpose: Accept result from earlier nlm_lock_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm4_lock_res_4_svc(arg, rqstp)
+ nlm4_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm4_lock_res", rqstp);
+
+ return (NULL);
+}
+
+/* nlm_cancel_res ---------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_cancel_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm4_cancel_res_4_svc(arg, rqstp)
+ nlm4_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm4_cancel_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_unlock_res ---------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_unlock_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm4_unlock_res_4_svc(arg, rqstp)
+ nlm4_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm4_unlock_res", rqstp);
+ return (NULL);
+}
+
+/* nlm_granted_res --------------------------------------------------------- */
+/*
+ * Purpose: Accept result from earlier nlm_granted_msg() call
+ * Returns: Nothing
+ */
+void *
+nlm4_granted_res_4_svc(arg, rqstp)
+ nlm4_res *arg;
+ struct svc_req *rqstp;
+{
+ if (debug_level)
+ log_from_addr("nlm4_granted_res", rqstp);
+ return (NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Calls for PCNFS locking (aka non-monitored locking, no involvement
+ * of rpc.statd).
+ *
+ * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
+ */
+
+/* nlm_share --------------------------------------------------------------- */
+/*
+ * Purpose: Establish a DOS-style lock
+ * Returns: success or failure
+ * Notes: Blocking locks are not supported - client is expected
+ * to retry if required.
+ */
+nlm4_shareres *
+nlm4_share_4_svc(arg, rqstp)
+ nlm4_shareargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_shareres res;
+
+ if (debug_level)
+ log_from_addr("nlm4_share", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat = nlm4_granted;
+ res.sequence = 1234356; /* X/Open says this field is ignored? */
+ return (&res);
+}
+
+/* nlm4_unshare ------------------------------------------------------------ */
+/*
+ * Purpose: Release a DOS-style lock
+ * Returns: nlm_granted, unless in grace period
+ * Notes:
+ */
+nlm4_shareres *
+nlm4_unshare_4_svc(arg, rqstp)
+ nlm4_shareargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_shareres res;
+
+ if (debug_level)
+ log_from_addr("nlm_unshare", rqstp);
+
+ res.cookie = arg->cookie;
+ res.stat = nlm4_granted;
+ res.sequence = 1234356; /* X/Open says this field is ignored? */
+ return (&res);
+}
+
+/* nlm4_nm_lock ------------------------------------------------------------ */
+/*
+ * Purpose: non-monitored version of nlm4_lock()
+ * Returns: as for nlm4_lock()
+ * Notes: These locks are in the same style as the standard nlm4_lock,
+ * but the rpc.statd should not be called to establish a
+ * monitor for the client machine, since that machine is
+ * declared not to be running a rpc.statd, and so would not
+ * respond to the statd protocol.
+ */
+nlm4_res *
+nlm4_nm_lock_4_svc(arg, rqstp)
+ nlm4_lockargs *arg;
+ struct svc_req *rqstp;
+{
+ static nlm4_res res;
+
+ if (debug_level)
+ log_from_addr("nlm4_nm_lock", rqstp);
+
+ /* copy cookie from arg to result. See comment in nlm4_test_1() */
+ res.cookie = arg->cookie;
+ res.stat.stat = nlm4_granted;
+ return (&res);
+}
+
+/* nlm4_free_all ------------------------------------------------------------ */
+/*
+ * Purpose: Release all locks held by a named client
+ * Returns: Nothing
+ * Notes: Potential denial of service security problem here - the
+ * locks to be released are specified by a host name, independent
+ * of the address from which the request has arrived.
+ * Should probably be rejected if the named host has been
+ * using monitored locks.
+ */
+void *
+nlm4_free_all_4_svc(arg, rqstp)
+ nlm_notify *arg;
+ struct svc_req *rqstp;
+{
+ static char dummy;
+
+ if (debug_level)
+ log_from_addr("nlm4_free_all", rqstp);
+ return (&dummy);
+}
+
+/* nlm_sm_notify --------------------------------------------------------- */
+/*
+ * Purpose: called by rpc.statd when a monitored host state changes.
+ * Returns: Nothing
+ */
+void *
+nlm_sm_notify_0_svc(arg, rqstp)
+ struct nlm_sm_status *arg;
+ struct svc_req *rqstp;
+{
+ static char dummy;
+ notify(arg->mon_name, arg->state);
+ return (&dummy);
+}
diff --git a/usr.sbin/rpc.lockd/lockd.c b/usr.sbin/rpc.lockd/lockd.c
index ac328569126e..e0ac5cf52994 100644
--- a/usr.sbin/rpc.lockd/lockd.c
+++ b/usr.sbin/rpc.lockd/lockd.c
@@ -1,3 +1,6 @@
+/* $NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $ */
+/* $FreeBSD$ */
+
/*
* Copyright (c) 1995
* A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
@@ -31,77 +34,193 @@
*
*/
+#include <sys/cdefs.h>
#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
+__RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $");
+#endif
+
+/*
+ * main() function for NFS lock daemon. Most of the code in this
+ * file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x.
+ *
+ * The actual program logic is in the file lock_proc.c
+ */
-/* main() function for NFS lock daemon. Most of the code in this */
-/* file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x */
-/* The actual program logic is in the file procs.c */
+#include <sys/types.h>
+#include <sys/socket.h>
#include <err.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
#include <string.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <netconfig.h>
+
#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
+#include <rpcsvc/sm_inter.h>
+
#include "lockd.h"
+#include <rpcsvc/nlm_prot.h>
+
+int debug_level = 0; /* 0 = no debugging syslog() calls */
+int _rpcsvcdirty = 0;
+
+int grace_expired;
-void nlm_prog_1 __P((struct svc_req *, SVCXPRT *));
-void nlm_prog_3 __P((struct svc_req *, SVCXPRT *));
-static void usage __P((void));
+int main __P((int, char **));
+void nlm_prog_0 __P((struct svc_req *, SVCXPRT *));
+void nlm_prog_1 __P((struct svc_req *, SVCXPRT *));
+void nlm_prog_3 __P((struct svc_req *, SVCXPRT *));
+void nlm_prog_4 __P((struct svc_req *, SVCXPRT *));
+void usage __P((void));
-int debug_level = 0; /* Zero means no debugging syslog() calls */
+void sigalarm_handler __P((int));
+
+char *transports[] = { "udp", "tcp", "udp6", "tcp6" };
int
-main(int argc, char **argv)
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ SVCXPRT *transp;
+ int ch, i, maxindex, s;
+ struct sigaction sigchild, sigalarm;
+ int grace_period = 30;
+ struct netconfig *nconf;
+
+ while ((ch = getopt(argc, argv, "d:g:")) != (-1)) {
+ switch (ch) {
+ case 'd':
+ debug_level = atoi(optarg);
+ if (!debug_level) {
+ usage();
+ /* NOTREACHED */
+ }
+ break;
+ case 'g':
+ grace_period = atoi(optarg);
+ if (!grace_period) {
+ usage();
+ /* NOTREACHED */
+ }
+ break;
+ default:
+ case '?':
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ if (geteuid()) { /* This command allowed only to root */
+ fprintf(stderr, "Sorry. You are not superuser\n");
+ exit(1);
+ }
+
+ (void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
+ (void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
+ (void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
+ (void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);
+
+ /*
+ * Check if IPv6 support is present.
+ */
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0)
+ maxindex = 2;
+ else {
+ close(s);
+ maxindex = 4;
+ }
+
+ for (i = 0; i < maxindex; i++) {
+ nconf = getnetconfigent(transports[i]);
+ if (nconf == NULL)
+ errx(1, "cannot get udp netconf.");
+
+ transp = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+ if (transp == NULL) {
+ errx(1, "cannot create %s service.", transports[i]);
+ /* NOTREACHED */
+ }
+ if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0, nconf)) {
+ errx(1, "unable to register (NLM_PROG, NLM_SM, %s)",
+ transports[i]);
+ /* NOTREACHED */
+ }
+ if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1, nconf)) {
+ errx(1, "unable to register (NLM_PROG, NLM_VERS, %s)",
+ transports[i]);
+ /* NOTREACHED */
+ }
+ if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, nconf)) {
+ errx(1, "unable to register (NLM_PROG, NLM_VERSX, %s)",
+ transports[i]);
+ /* NOTREACHED */
+ }
+ if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, nconf)) {
+ errx(1, "unable to register (NLM_PROG, NLM_VERS4, %s)",
+ transports[i]);
+ /* NOTREACHED */
+ }
+ freenetconfigent(nconf);
+ }
+
+ /*
+ * Note that it is NOT sensible to run this program from inetd - the
+ * protocol assumes that it will run immediately at boot time.
+ */
+ if (daemon(0, 0)) {
+ err(1, "cannot fork");
+ /* NOTREACHED */
+ }
+
+ openlog("rpc.lockd", 0, LOG_DAEMON);
+ if (debug_level)
+ syslog(LOG_INFO, "Starting, debug level %d", debug_level);
+ else
+ syslog(LOG_INFO, "Starting");
+
+ sigchild.sa_handler = sigchild_handler;
+ sigemptyset(&sigchild.sa_mask);
+ sigchild.sa_flags = SA_RESTART;
+ if (sigaction(SIGCHLD, &sigchild, NULL) != 0) {
+ syslog(LOG_WARNING, "sigaction(SIGCHLD) failed: %s",
+ strerror(errno));
+ exit(1);
+ }
+ sigalarm.sa_handler = sigalarm_handler;
+ sigemptyset(&sigalarm.sa_mask);
+ sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
+ sigalarm.sa_flags |= SA_RESTART;
+ if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
+ syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
+ strerror(errno));
+ exit(1);
+ }
+ grace_expired = 0;
+ if (alarm(10) < 0) {
+ syslog(LOG_WARNING, "alarm failed: %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ svc_run(); /* Should never return */
+ exit(1);
+}
+
+void
+sigalarm_handler(s)
+ int s;
{
- SVCXPRT *transp;
-
- if (argc > 1)
- {
- if (strncmp(argv[1], "-d", 2))
- usage();
- if (argc > 2) debug_level = atoi(argv[2]);
- else debug_level = atoi(argv[1] + 2);
- /* Ensure at least some debug if -d with no specified level */
- if (!debug_level) debug_level = 1;
- }
-
- (void)pmap_unset(NLM_PROG, NLM_VERS);
- (void)pmap_unset(NLM_PROG, NLM_VERSX);
-
- transp = svcudp_create(RPC_ANYSOCK);
- if (transp == NULL)
- errx(1, "cannot create udp service");
- if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_UDP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS, udp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_UDP))
- errx(1, "unable to register (NLM_PROG, NLM_VERSX, udp)");
-
- transp = svctcp_create(RPC_ANYSOCK, 0, 0);
- if (transp == NULL)
- errx(1, "cannot create tcp service");
- if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_TCP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS, tcp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_TCP))
- errx(1, "unable to register (NLM_PROG, NLM_VERSX, tcp)");
-
- /* Note that it is NOT sensible to run this program from inetd - the */
- /* protocol assumes that it will run immediately at boot time. */
- if (daemon(0,0))
- err(1, "fork");
- openlog("rpc.lockd", 0, LOG_DAEMON);
- if (debug_level) syslog(LOG_INFO, "Starting, debug level %d", debug_level);
- else syslog(LOG_INFO, "Starting");
-
- svc_run(); /* Should never return */
- exit(1);
+ grace_expired = 1;
}
-static void
+void
usage()
{
- fprintf(stderr, "usage: rpc.lockd [-d [debuglevel]]\n");
- exit(1);
+ errx(1, "usage: rpc.lockd [-d <debuglevel>] [-g <grace period>]");
}
diff --git a/usr.sbin/rpc.lockd/lockd.h b/usr.sbin/rpc.lockd/lockd.h
index 39586bfd77ae..42f14f1f2956 100644
--- a/usr.sbin/rpc.lockd/lockd.h
+++ b/usr.sbin/rpc.lockd/lockd.h
@@ -1,3 +1,6 @@
+/* $NetBSD: lockd.h,v 1.2 2000/06/07 14:34:40 bouyer Exp $ */
+/* $FreeBSD$ */
+
/*
* Copyright (c) 1995
* A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
@@ -31,14 +34,6 @@
*
*/
-
-
-#include <stdio.h>
-#include <rpc/rpc.h>
-#include <syslog.h>
-#include <rpcsvc/sm_inter.h> /* protocol to talk to rpc.statd */
-#include "nlm_prot.h" /* The protocol we are implementing */
-
-
-/* global variables ------------------------------------------------------- */
-extern int debug_level;
+extern int debug_level;
+extern int grace_expired;
+void sigchild_handler __P((int));
diff --git a/usr.sbin/rpc.lockd/lockd_lock.c b/usr.sbin/rpc.lockd/lockd_lock.c
new file mode 100644
index 000000000000..998a2009e82c
--- /dev/null
+++ b/usr.sbin/rpc.lockd/lockd_lock.c
@@ -0,0 +1,759 @@
+/* $NetBSD: lockd_lock.c,v 1.5 2000/11/21 03:47:41 enami Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 Manuel Bouyer.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 BY THE REGENTS 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 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 <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+#include <rpcsvc/sm_inter.h>
+#include <rpcsvc/nlm_prot.h>
+#include "lockd_lock.h"
+#include "lockd.h"
+
+/* A set of utilities for managing file locking */
+LIST_HEAD(lcklst_head, file_lock);
+struct lcklst_head lcklst_head = LIST_HEAD_INITIALIZER(lcklst_head);
+
+/* struct describing a lock */
+struct file_lock {
+ LIST_ENTRY(file_lock) lcklst;
+ fhandle_t filehandle; /* NFS filehandle */
+ struct sockaddr *addr;
+ struct nlm4_holder client; /* lock holder */
+ netobj client_cookie; /* cookie sent by the client */
+ char client_name[128];
+ int nsm_status; /* status from the remote lock manager */
+ int status; /* lock status, see below */
+ int flags; /* lock flags, see lockd_lock.h */
+ pid_t locker; /* pid of the child process trying to get the lock */
+ int fd; /* file descriptor for this lock */
+};
+
+/* lock status */
+#define LKST_LOCKED 1 /* lock is locked */
+#define LKST_WAITING 2 /* file is already locked by another host */
+#define LKST_PROCESSING 3 /* child is trying to aquire the lock */
+#define LKST_DYING 4 /* must dies when we get news from the child */
+
+void lfree __P((struct file_lock *));
+enum nlm_stats do_lock __P((struct file_lock *, int));
+enum nlm_stats do_unlock __P((struct file_lock *));
+void send_granted __P((struct file_lock *, int));
+void siglock __P((void));
+void sigunlock __P((void));
+
+/* list of hosts we monitor */
+LIST_HEAD(hostlst_head, host);
+struct hostlst_head hostlst_head = LIST_HEAD_INITIALIZER(hostlst_head);
+
+/* struct describing a lock */
+struct host {
+ LIST_ENTRY(host) hostlst;
+ char name[SM_MAXSTRLEN];
+ int refcnt;
+};
+
+void do_mon __P((char *));
+
+/*
+ * testlock(): inform the caller if the requested lock would be granted or not
+ * returns NULL if lock would granted, or pointer to the current nlm4_holder
+ * otherwise.
+ */
+
+struct nlm4_holder *
+testlock(lock, flags)
+ struct nlm4_lock *lock;
+ int flags;
+{
+ struct file_lock *fl;
+ fhandle_t filehandle;
+
+ /* convert lock to a local filehandle */
+ memcpy(&filehandle, lock->fh.n_bytes, sizeof(filehandle));
+
+ siglock();
+ /* search through the list for lock holder */
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL;
+ fl = LIST_NEXT(fl, lcklst)) {
+ if (fl->status != LKST_LOCKED)
+ continue;
+ if (memcmp(&fl->filehandle, &filehandle, sizeof(filehandle)))
+ continue;
+ /* got it ! */
+ syslog(LOG_DEBUG, "test for %s: found lock held by %s",
+ lock->caller_name, fl->client_name);
+ sigunlock();
+ return (&fl->client);
+ }
+ /* not found */
+ sigunlock();
+ syslog(LOG_DEBUG, "test for %s: no lock found", lock->caller_name);
+ return NULL;
+}
+
+/*
+ * getlock: try to aquire the lock.
+ * If file is already locked and we can sleep, put the lock in the list with
+ * status LKST_WAITING; it'll be processed later.
+ * Otherwise try to lock. If we're allowed to block, fork a child which
+ * will do the blocking lock.
+ */
+enum nlm_stats
+getlock(lckarg, rqstp, flags)
+ nlm4_lockargs * lckarg;
+ struct svc_req *rqstp;
+ int flags;
+{
+ struct file_lock *fl, *newfl;
+ enum nlm_stats retval;
+
+ if (grace_expired == 0 && lckarg->reclaim == 0)
+ return (flags & LOCK_V4) ?
+ nlm4_denied_grace_period : nlm_denied_grace_period;
+
+ /* allocate new file_lock for this request */
+ newfl = malloc(sizeof(struct file_lock));
+ if (newfl == NULL) {
+ syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
+ /* failed */
+ return (flags & LOCK_V4) ?
+ nlm4_denied_nolock : nlm_denied_nolocks;
+ }
+ if (lckarg->alock.fh.n_len != sizeof(fhandle_t)) {
+ syslog(LOG_DEBUG, "recieved fhandle size %d, local size %d",
+ lckarg->alock.fh.n_len, (int)sizeof(fhandle_t));
+ }
+ memcpy(&newfl->filehandle, lckarg->alock.fh.n_bytes, sizeof(fhandle_t));
+ newfl->addr = (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf;
+ newfl->client.exclusive = lckarg->exclusive;
+ newfl->client.svid = lckarg->alock.svid;
+ newfl->client.oh.n_bytes = malloc(lckarg->alock.oh.n_len);
+ if (newfl->client.oh.n_bytes == NULL) {
+ syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
+ free(newfl);
+ return (flags & LOCK_V4) ?
+ nlm4_denied_nolock : nlm_denied_nolocks;
+ }
+ newfl->client.oh.n_len = lckarg->alock.oh.n_len;
+ memcpy(newfl->client.oh.n_bytes, lckarg->alock.oh.n_bytes,
+ lckarg->alock.oh.n_len);
+ newfl->client.l_offset = lckarg->alock.l_offset;
+ newfl->client.l_len = lckarg->alock.l_len;
+ newfl->client_cookie.n_len = lckarg->cookie.n_len;
+ newfl->client_cookie.n_bytes = malloc(lckarg->cookie.n_len);
+ if (newfl->client_cookie.n_bytes == NULL) {
+ syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
+ free(newfl->client.oh.n_bytes);
+ free(newfl);
+ return (flags & LOCK_V4) ?
+ nlm4_denied_nolock : nlm_denied_nolocks;
+ }
+ memcpy(newfl->client_cookie.n_bytes, lckarg->cookie.n_bytes,
+ lckarg->cookie.n_len);
+ strncpy(newfl->client_name, lckarg->alock.caller_name, 128);
+ newfl->nsm_status = lckarg->state;
+ newfl->status = 0;
+ newfl->flags = flags;
+ siglock();
+ /* look for a lock rq from this host for this fh */
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL;
+ fl = LIST_NEXT(fl, lcklst)) {
+ if (memcmp(&newfl->filehandle, &fl->filehandle,
+ sizeof(fhandle_t)) == 0) {
+ if (strcmp(newfl->client_name, fl->client_name) == 0 &&
+ newfl->client.svid == fl->client.svid) {
+ /* already locked by this host ??? */
+ sigunlock();
+ syslog(LOG_NOTICE, "duplicate lock from %s",
+ newfl->client_name);
+ lfree(newfl);
+ switch(fl->status) {
+ case LKST_LOCKED:
+ return (flags & LOCK_V4) ?
+ nlm4_granted : nlm_granted;
+ case LKST_WAITING:
+ case LKST_PROCESSING:
+ return (flags & LOCK_V4) ?
+ nlm4_blocked : nlm_blocked;
+ case LKST_DYING:
+ return (flags & LOCK_V4) ?
+ nlm4_denied : nlm_denied;
+ default:
+ syslog(LOG_NOTICE, "bad status %d",
+ fl->status);
+ return (flags & LOCK_V4) ?
+ nlm4_failed : nlm_denied;
+ }
+ }
+ /*
+ * We already have a lock for this file. Put this one
+ * in waiting state if allowed to block
+ */
+ if (lckarg->block) {
+ syslog(LOG_DEBUG, "lock from %s: already "
+ "locked, waiting",
+ lckarg->alock.caller_name);
+ newfl->status = LKST_WAITING;
+ LIST_INSERT_HEAD(&lcklst_head, newfl, lcklst);
+ do_mon(lckarg->alock.caller_name);
+ sigunlock();
+ return (flags & LOCK_V4) ?
+ nlm4_blocked : nlm_blocked;
+ } else {
+ sigunlock();
+ syslog(LOG_DEBUG, "lock from %s: already "
+ "locked, failed",
+ lckarg->alock.caller_name);
+ lfree(newfl);
+ return (flags & LOCK_V4) ?
+ nlm4_denied : nlm_denied;
+ }
+ }
+ }
+ /* no entry for this file yet; add to list */
+ LIST_INSERT_HEAD(&lcklst_head, newfl, lcklst);
+ /* do the lock */
+ retval = do_lock(newfl, lckarg->block);
+ switch (retval) {
+ case nlm4_granted:
+ /* case nlm_granted: is the same as nlm4_granted */
+ case nlm4_blocked:
+ /* case nlm_blocked: is the same as nlm4_blocked */
+ do_mon(lckarg->alock.caller_name);
+ break;
+ default:
+ lfree(newfl);
+ break;
+ }
+ sigunlock();
+ return retval;
+}
+
+/* unlock a filehandle */
+enum nlm_stats
+unlock(lck, flags)
+ nlm4_lock *lck;
+ int flags;
+{
+ struct file_lock *fl;
+ fhandle_t filehandle;
+ int err = (flags & LOCK_V4) ? nlm4_granted : nlm_granted;
+
+ memcpy(&filehandle, lck->fh.n_bytes, sizeof(fhandle_t));
+ siglock();
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL;
+ fl = LIST_NEXT(fl, lcklst)) {
+ if (strcmp(fl->client_name, lck->caller_name) ||
+ memcmp(&filehandle, &fl->filehandle, sizeof(fhandle_t)) ||
+ fl->client.oh.n_len != lck->oh.n_len ||
+ memcmp(fl->client.oh.n_bytes, lck->oh.n_bytes,
+ fl->client.oh.n_len) != 0 ||
+ fl->client.svid != lck->svid)
+ continue;
+ /* Got it, unlock and remove from the queue */
+ syslog(LOG_DEBUG, "unlock from %s: found struct, status %d",
+ lck->caller_name, fl->status);
+ switch (fl->status) {
+ case LKST_LOCKED:
+ err = do_unlock(fl);
+ break;
+ case LKST_WAITING:
+ /* remove from the list */
+ LIST_REMOVE(fl, lcklst);
+ lfree(fl);
+ break;
+ case LKST_PROCESSING:
+ /*
+ * being handled by a child; will clean up
+ * when the child exits
+ */
+ fl->status = LKST_DYING;
+ break;
+ case LKST_DYING:
+ /* nothing to do */
+ break;
+ default:
+ syslog(LOG_NOTICE, "unknow status %d for %s",
+ fl->status, fl->client_name);
+ }
+ sigunlock();
+ return err;
+ }
+ sigunlock();
+ /* didn't find a matching entry; log anyway */
+ syslog(LOG_NOTICE, "no matching entry for %s",
+ lck->caller_name);
+ return (flags & LOCK_V4) ? nlm4_granted : nlm_granted;
+}
+
+void
+lfree(fl)
+ struct file_lock *fl;
+{
+ free(fl->client.oh.n_bytes);
+ free(fl->client_cookie.n_bytes);
+ free(fl);
+}
+
+void
+sigchild_handler(sig)
+ int sig;
+{
+ int status;
+ pid_t pid;
+ struct file_lock *fl;
+
+ while (1) {
+ pid = wait4(-1, &status, WNOHANG, NULL);
+ if (pid == -1) {
+ if (errno != ECHILD)
+ syslog(LOG_NOTICE, "wait failed: %s",
+ strerror(errno));
+ else
+ syslog(LOG_DEBUG, "wait failed: %s",
+ strerror(errno));
+ return;
+ }
+ if (pid == 0) {
+ /* no more child to handle yet */
+ return;
+ }
+ /*
+ * if we're here we have a child that exited
+ * Find the associated file_lock.
+ */
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL;
+ fl = LIST_NEXT(fl, lcklst)) {
+ if (pid == fl->locker)
+ break;
+ }
+ if (pid != fl->locker) {
+ syslog(LOG_NOTICE, "unknow child %d", pid);
+ } else {
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ syslog(LOG_NOTICE, "child %d failed", pid);
+ /*
+ * can't do much here; we can't reply
+ * anything but OK for blocked locks
+ * Eventually the client will time out
+ * and retry.
+ */
+ do_unlock(fl);
+ return;
+ }
+
+ /* check lock status */
+ syslog(LOG_DEBUG, "processing child %d, status %d",
+ pid, fl->status);
+ switch(fl->status) {
+ case LKST_PROCESSING:
+ fl->status = LKST_LOCKED;
+ send_granted(fl, (fl->flags & LOCK_V4) ?
+ nlm4_granted : nlm_granted);
+ break;
+ case LKST_DYING:
+ do_unlock(fl);
+ break;
+ default:
+ syslog(LOG_NOTICE, "bad lock status (%d) for"
+ " child %d", fl->status, pid);
+ }
+ }
+ }
+}
+
+/*
+ *
+ * try to aquire the lock described by fl. Eventually fock a child to do a
+ * blocking lock if allowed and required.
+ */
+
+enum nlm_stats
+do_lock(fl, block)
+ struct file_lock *fl;
+ int block;
+{
+ int lflags, error;
+ struct stat st;
+
+ fl->fd = fhopen(&fl->filehandle, O_RDWR);
+ if (fl->fd < 0) {
+ switch (errno) {
+ case ESTALE:
+ error = nlm4_stale_fh;
+ break;
+ case EROFS:
+ error = nlm4_rofs;
+ break;
+ default:
+ error = nlm4_failed;
+ }
+ if ((fl->flags & LOCK_V4) == 0)
+ error = nlm_denied;
+ syslog(LOG_NOTICE, "fhopen failed (from %s): %s",
+ fl->client_name, strerror(errno));
+ LIST_REMOVE(fl, lcklst);
+ return error;;
+ }
+ if (fstat(fl->fd, &st) < 0) {
+ syslog(LOG_NOTICE, "fstat failed (from %s): %s",
+ fl->client_name, strerror(errno));
+ }
+ syslog(LOG_DEBUG, "lock from %s for file%s%s: dev %d ino %d (uid %d), "
+ "flags %d",
+ fl->client_name, fl->client.exclusive ? " (exclusive)":"",
+ block ? " (block)":"",
+ st.st_dev, st.st_ino, st.st_uid, fl->flags);
+ lflags = LOCK_NB;
+ if (fl->client.exclusive == 0)
+ lflags |= LOCK_SH;
+ else
+ lflags |= LOCK_EX;
+ error = flock(fl->fd, lflags);
+ if (error != 0 && errno == EAGAIN && block) {
+ switch (fl->locker = fork()) {
+ case -1: /* fork failed */
+ syslog(LOG_NOTICE, "fork failed: %s", strerror(errno));
+ LIST_REMOVE(fl, lcklst);
+ close(fl->fd);
+ return (fl->flags & LOCK_V4) ?
+ nlm4_denied_nolock : nlm_denied_nolocks;
+ case 0:
+ /*
+ * Attempt a blocking lock. Will have to call
+ * NLM_GRANTED later.
+ */
+ setproctitle("%s", fl->client_name);
+ lflags &= ~LOCK_NB;
+ if(flock(fl->fd, lflags) != 0) {
+ syslog(LOG_NOTICE, "flock failed: %s",
+ strerror(errno));
+ exit(-1);
+ }
+ /* lock granted */
+ exit(0);
+ default:
+ syslog(LOG_DEBUG, "lock request from %s: forked %d",
+ fl->client_name, fl->locker);
+ fl->status = LKST_PROCESSING;
+ return (fl->flags & LOCK_V4) ?
+ nlm4_blocked : nlm_blocked;
+ }
+ }
+ /* non block case */
+ if (error != 0) {
+ switch (errno) {
+ case EAGAIN:
+ error = nlm4_denied;
+ break;
+ case ESTALE:
+ error = nlm4_stale_fh;
+ break;
+ case EROFS:
+ error = nlm4_rofs;
+ break;
+ default:
+ error = nlm4_failed;
+ }
+ if ((fl->flags & LOCK_V4) == 0)
+ error = nlm_denied;
+ if (errno != EAGAIN)
+ syslog(LOG_NOTICE, "flock for %s failed: %s",
+ fl->client_name, strerror(errno));
+ else syslog(LOG_DEBUG, "flock for %s failed: %s",
+ fl->client_name, strerror(errno));
+ LIST_REMOVE(fl, lcklst);
+ close(fl->fd);
+ return error;
+ }
+ fl->status = LKST_LOCKED;
+ return (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
+}
+
+void
+send_granted(fl, opcode)
+ struct file_lock *fl;
+ int opcode;
+{
+ CLIENT *cli;
+ static char dummy;
+ struct timeval timeo;
+ int success;
+ static struct nlm_res retval;
+ static struct nlm4_res retval4;
+
+ cli = get_client(fl->addr,
+ (fl->flags & LOCK_V4) ? NLM_VERS4 : NLM_VERS);
+ if (cli == NULL) {
+ syslog(LOG_NOTICE, "failed to get CLIENT for %s",
+ fl->client_name);
+ /*
+ * We fail to notify remote that the lock has been granted.
+ * The client will timeout and retry, the lock will be
+ * granted at this time.
+ */
+ return;
+ }
+ timeo.tv_sec = 0;
+ timeo.tv_usec = (fl->flags & LOCK_ASYNC) ? 0 : 500000; /* 0.5s */
+
+ if (fl->flags & LOCK_V4) {
+ static nlm4_testargs res;
+ res.cookie = fl->client_cookie;
+ res.exclusive = fl->client.exclusive;
+ res.alock.caller_name = fl->client_name;
+ res.alock.fh.n_len = sizeof(fhandle_t);
+ res.alock.fh.n_bytes = (char*)&fl->filehandle;
+ res.alock.oh = fl->client.oh;
+ res.alock.svid = fl->client.svid;
+ res.alock.l_offset = fl->client.l_offset;
+ res.alock.l_len = fl->client.l_len;
+ syslog(LOG_DEBUG, "sending v4 reply%s",
+ (fl->flags & LOCK_ASYNC) ? " (async)":"");
+ if (fl->flags & LOCK_ASYNC) {
+ success = clnt_call(cli, NLM4_GRANTED_MSG,
+ xdr_nlm4_testargs, &res, xdr_void, &dummy, timeo);
+ } else {
+ success = clnt_call(cli, NLM4_GRANTED,
+ xdr_nlm4_testargs, &res, xdr_nlm4_res,
+ &retval4, timeo);
+ }
+ } else {
+ static nlm_testargs res;
+
+ res.cookie = fl->client_cookie;
+ res.exclusive = fl->client.exclusive;
+ res.alock.caller_name = fl->client_name;
+ res.alock.fh.n_len = sizeof(fhandle_t);
+ res.alock.fh.n_bytes = (char*)&fl->filehandle;
+ res.alock.oh = fl->client.oh;
+ res.alock.svid = fl->client.svid;
+ res.alock.l_offset = fl->client.l_offset;
+ res.alock.l_len = fl->client.l_len;
+ syslog(LOG_DEBUG, "sending v1 reply%s",
+ (fl->flags & LOCK_ASYNC) ? " (async)":"");
+ if (fl->flags & LOCK_ASYNC) {
+ success = clnt_call(cli, NLM_GRANTED_MSG,
+ xdr_nlm_testargs, &res, xdr_void, &dummy, timeo);
+ } else {
+ success = clnt_call(cli, NLM_GRANTED,
+ xdr_nlm_testargs, &res, xdr_nlm_res,
+ &retval, timeo);
+ }
+ }
+ if (debug_level > 2)
+ syslog(LOG_DEBUG, "clnt_call returns %d(%s) for granted",
+ success, clnt_sperrno(success));
+
+}
+
+enum nlm_stats
+do_unlock(rfl)
+ struct file_lock *rfl;
+{
+ struct file_lock *fl;
+ int error;
+ int lockst;
+
+ /* unlock the file: closing is enouth ! */
+ if (close(rfl->fd) < 0) {
+ if (errno == ESTALE)
+ error = nlm4_stale_fh;
+ else
+ error = nlm4_failed;
+ if ((fl->flags & LOCK_V4) == 0)
+ error = nlm_denied;
+ syslog(LOG_NOTICE,
+ "close failed (from %s): %s",
+ rfl->client_name, strerror(errno));
+ } else {
+ error = (fl->flags & LOCK_V4) ?
+ nlm4_granted : nlm_granted;
+ }
+ LIST_REMOVE(rfl, lcklst);
+
+ /* process the next LKST_WAITING lock request for this fh */
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL;
+ fl = LIST_NEXT(fl, lcklst)) {
+ if (fl->status != LKST_WAITING ||
+ memcmp(&rfl->filehandle, &fl->filehandle,
+ sizeof(fhandle_t)) != 0)
+ continue;
+
+ lockst = do_lock(fl, 1); /* If it's LKST_WAITING we can block */
+ switch (lockst) {
+ case nlm4_granted:
+ /* case nlm_granted: same as nlm4_granted */
+ send_granted(fl, (fl->flags & LOCK_V4) ?
+ nlm4_granted : nlm_granted);
+ break;
+ case nlm4_blocked:
+ /* case nlm_blocked: same as nlm4_blocked */
+ break;
+ default:
+ lfree(fl);
+ break;
+ }
+ break;
+ }
+ return error;
+}
+
+void
+siglock()
+{
+ sigset_t block;
+
+ sigemptyset(&block);
+ sigaddset(&block, SIGCHLD);
+
+ if (sigprocmask(SIG_BLOCK, &block, NULL) < 0) {
+ syslog(LOG_WARNING, "siglock failed: %s", strerror(errno));
+ }
+}
+
+void
+sigunlock()
+{
+ sigset_t block;
+
+ sigemptyset(&block);
+ sigaddset(&block, SIGCHLD);
+
+ if (sigprocmask(SIG_UNBLOCK, &block, NULL) < 0) {
+ syslog(LOG_WARNING, "sigunlock failed: %s", strerror(errno));
+ }
+}
+
+/* monitor a host through rpc.statd, and keep a ref count */
+void
+do_mon(hostname)
+ char *hostname;
+{
+ struct host *hp;
+ struct mon my_mon;
+ struct sm_stat_res res;
+ int retval;
+
+ for (hp = LIST_FIRST(&hostlst_head); hp != NULL;
+ hp = LIST_NEXT(hp, hostlst)) {
+ if (strcmp(hostname, hp->name) == 0) {
+ /* already monitored, just bump refcnt */
+ hp->refcnt++;
+ return;
+ }
+ }
+ /* not found, have to create an entry for it */
+ hp = malloc(sizeof(struct host));
+ strncpy(hp->name, hostname, SM_MAXSTRLEN);
+ hp->refcnt = 1;
+ syslog(LOG_DEBUG, "monitoring host %s",
+ hostname);
+ memset(&my_mon, 0, sizeof(my_mon));
+ my_mon.mon_id.mon_name = hp->name;
+ my_mon.mon_id.my_id.my_name = "localhost";
+ my_mon.mon_id.my_id.my_prog = NLM_PROG;
+ my_mon.mon_id.my_id.my_vers = NLM_SM;
+ my_mon.mon_id.my_id.my_proc = NLM_SM_NOTIFY;
+ if ((retval =
+ callrpc("localhost", SM_PROG, SM_VERS, SM_MON, xdr_mon,
+ (char*)&my_mon, xdr_sm_stat_res, (char*)&res)) != 0) {
+ syslog(LOG_WARNING, "rpc to statd failed: %s",
+ clnt_sperrno((enum clnt_stat)retval));
+ free(hp);
+ return;
+ }
+ if (res.res_stat == stat_fail) {
+ syslog(LOG_WARNING, "statd failed");
+ free(hp);
+ return;
+ }
+ LIST_INSERT_HEAD(&hostlst_head, hp, hostlst);
+}
+
+void
+notify(hostname, state)
+ char *hostname;
+ int state;
+{
+ struct file_lock *fl, *next_fl;
+ int err;
+ syslog(LOG_DEBUG, "notify from %s, new state %d", hostname, state);
+ /* search all lock for this host; if status changed, release the lock */
+ siglock();
+ for (fl = LIST_FIRST(&lcklst_head); fl != NULL; fl = next_fl) {
+ next_fl = LIST_NEXT(fl, lcklst);
+ if (strcmp(hostname, fl->client_name) == 0 &&
+ fl->nsm_status != state) {
+ syslog(LOG_DEBUG, "state %d, nsm_state %d, unlocking",
+ fl->status, fl->nsm_status);
+ switch(fl->status) {
+ case LKST_LOCKED:
+ err = do_unlock(fl);
+ if (err != nlm_granted)
+ syslog(LOG_DEBUG,
+ "notify: unlock failed for %s (%d)",
+ hostname, err);
+ break;
+ case LKST_WAITING:
+ LIST_REMOVE(fl, lcklst);
+ lfree(fl);
+ break;
+ case LKST_PROCESSING:
+ fl->status = LKST_DYING;
+ break;
+ case LKST_DYING:
+ break;
+ default:
+ syslog(LOG_NOTICE, "unknow status %d for %s",
+ fl->status, fl->client_name);
+ }
+ }
+ }
+ sigunlock();
+}
diff --git a/usr.sbin/rpc.lockd/lockd_lock.h b/usr.sbin/rpc.lockd/lockd_lock.h
new file mode 100644
index 000000000000..5b0232f69d13
--- /dev/null
+++ b/usr.sbin/rpc.lockd/lockd_lock.h
@@ -0,0 +1,21 @@
+/* $NetBSD: lockd_lock.h,v 1.2 2000/06/09 14:00:54 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/* Headers and function declarations for file-locking utilities */
+
+struct nlm4_holder * testlock __P((struct nlm4_lock *, int));
+
+enum nlm_stats getlock __P((nlm4_lockargs *, struct svc_req *, int));
+enum nlm_stats unlock __P((nlm4_lock *, int));
+void notify __P((char *, int));
+
+/* flags for testlock, getlock & unlock */
+#define LOCK_ASYNC 0x01 /* async version (getlock only) */
+#define LOCK_V4 0x02 /* v4 version */
+#define LOCK_MON 0x04 /* monitored lock (getlock only) */
+#define LOCK_CANCEL 0x08 /* cancel, not unlock request (unlock only) */
+
+/* callbacks from lock_proc.c */
+void transmit_result __P((int, nlm_res *, struct sockaddr *));
+void transmit4_result __P((int, nlm4_res *, struct sockaddr *));
+CLIENT *get_client __P((struct sockaddr *, rpcvers_t));
diff --git a/usr.sbin/rpc.lockd/rpc.lockd.8 b/usr.sbin/rpc.lockd/rpc.lockd.8
index 2438aacf85d0..e87f5bb92c00 100644
--- a/usr.sbin/rpc.lockd/rpc.lockd.8
+++ b/usr.sbin/rpc.lockd/rpc.lockd.8
@@ -1,4 +1,5 @@
-.\" -*- nroff -*-
+.\" $NetBSD: rpc.lockd.8,v 1.5 2000/06/09 18:51:47 cgd Exp $
+.\" $FreeBSD$
.\"
.\" Copyright (c) 1995 A.R.Gordon, andrew.gordon@net-tel.co.uk
.\" All rights reserved.
@@ -31,7 +32,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
.\"
.Dd September 24, 1995
.Dt RPC.LOCKD 8
@@ -41,34 +41,64 @@
.Nd NFS file locking daemon
.Sh SYNOPSIS
.Nm
-.Op Fl d Op Ar debug_level
+.Op Fl d Ar debug_level
+.Op Fl g Ar grace period
.Sh DESCRIPTION
-.Nm Rpc.lockd
-is a daemon which provides file- and record-locking services in an NFS
-environment.
+The
+.Nm
+daemon provides monitored and unmonitored file and record locking services
+in an NFS environment.
+To monitor the status of hosts requesting locks,
+the locking daemon typically operates in conjunction
+with
+.Xr rpc.statd 8 .
.Pp
-The following option is available:
+Options and operands available for
+.Nm :
.Bl -tag -width indent
.It Fl d
-Cause debugging information to be written to syslog, recording
-all RPC transactions to the daemon. These messages are logged with level
-LOG_DEBUG and facility LOG_DAEMON. If debug_level is not specified,
-level 1 is assumed, giving one log line per protocol operation. Higher
+The
+.Fl d
+option causes debugging information to be written to syslog, recording
+all RPC transactions to the daemon.
+These messages are logged with level
+.Dv LOG_DEBUG
+and facility
+.Dv LOG_DAEMON .
+Specifying a
+.Ar debug_level
+of 1 results
+in the generation of one log line per protocol operation.
+Higher
debug levels can be specified, causing display of operation arguments
and internal operations of the daemon.
+.It Fl g
+The
+.Fl g
+option allow to specify the
+.Ar grace period ,
+in seconds.
+During the grace period
+.Nm
+only accepts requests from hosts which are reinitialising locks which
+existed before the server restart.
+Default is 30 seconds.
.El
.Pp
Error conditions are logged to syslog, irrespective of the debug level,
-using log level LOG_ERR and facility LOG_DAEMON.
+using log level
+.Dv LOG_ERR
+and facility
+.Dv LOG_DAEMON .
.Pp
The
.Nm
daemon must NOT be invoked by
.Xr inetd 8
because the protocol assumes that the daemon will run from system start time.
-Instead, it should be run from
-.Xr rc 8
-after the network has been started.
+Instead, it should be configured in
+.Xr rc.conf 5
+to run at system startup.
.Sh FILES
.Bl -tag -width /usr/include/rpcsvc/nlm_prot.x -compact
.It Pa /usr/include/rpcsvc/nlm_prot.x
@@ -76,21 +106,32 @@ RPC protocol specification for the network lock manager protocol.
.El
.Sh SEE ALSO
.Xr syslog 3 ,
-.Xr rc 8 ,
+.Xr rc.conf 5 ,
.Xr rpc.statd 8
.Sh BUGS
The current implementation provides only the server side of the protocol
-(ie. clients running other OS types can establish locks on a
+(i.e., clients running other OS types can establish locks on a
.Fx
+/
+.Nx
fileserver,
but there is currently no means for a
.Fx
+/
+.Nx
client to establish locks).
.Pp
-Versions 1, 2 and 3 of the protocol are supported. However, only versions
-2 (Unix systems) and 3 (PC-NFS clients) seem to be in common use - the version
-1 support has not been tested due to the lack of version 1 clients against
-which to test.
+The current implementation serialises locks requests that could be shared.
.Sh STANDARDS
-The implementation is based on the specification in X/Open CAE Specification
-C218, "Protocols for X/Open PC Interworking: XNFS, Issue 4", ISBN 1 872630 66 9
+The implementation is based on the specification in
+.Rs
+.%B "X/Open CAE Specification C218"
+.%T "Protocols for X/Open PC Interworking: XNFS, Issue 4"
+.%O ISBN 1 872630 66 9
+.Re
+.Sh HISTORY
+A version of
+.Nm
+appeared in
+.Tn SunOS
+4.
diff --git a/usr.sbin/rpc.lockd/test.c b/usr.sbin/rpc.lockd/test.c
index 0dd8eaefa09e..a751e5c6f4e4 100644
--- a/usr.sbin/rpc.lockd/test.c
+++ b/usr.sbin/rpc.lockd/test.c
@@ -1,14 +1,17 @@
+/* $NetBSD: test.c,v 1.2 1997/10/18 04:01:21 lukem Exp $ */
+
+#include <sys/cdefs.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nlm_prot.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro";
static char sccsid[] = "from: * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC";
+#else
+__RCSID("$NetBSD: test.c,v 1.2 1997/10/18 04:01:21 lukem Exp $");
+static const char rcsid[] = "$FreeBSD$";
#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <rpc/rpc.h>
-#include <rpcsvc/nlm_prot.h>
+#endif /* not lint */
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 0, 0 };
@@ -304,63 +307,59 @@ nlm_free_all_3(argp, clnt)
int main(int argc, char **argv)
{
- CLIENT *cli;
- nlm_res res_block;
- nlm_res *out;
- nlm_lockargs arg;
- struct timeval tim;
-
- printf("Creating client for host %s\n", argv[1]);
- cli = clnt_create(argv[1], NLM_PROG, NLM_VERS, "udp");
- if (!cli)
- {
- printf("Failed to create client\n");
- exit(1);
- }
-
-
- clnt_control(cli, CLGET_TIMEOUT, &tim);
- printf("Default timeout was %d.%d\n", tim.tv_sec, tim.tv_usec);
- tim.tv_usec = -1;
- tim.tv_sec = -1;
- clnt_control(cli, CLSET_TIMEOUT, &tim);
- clnt_control(cli, CLGET_TIMEOUT, &tim);
- printf("timeout now %d.%d\n", tim.tv_sec, tim.tv_usec);
-
-
- arg.cookie.n_len = 4;
- arg.cookie.n_bytes = "hello";
- arg.block = 0;
- arg.exclusive = 0;
- arg.reclaim = 0;
- arg.state = 0x1234;
- arg.alock.caller_name = "localhost";
- arg.alock.fh.n_len = 32;
- arg.alock.fh.n_bytes = "\x04\x04\x02\x00\x01\x00\x00\x00\x0c\x00\x00\x00\xff\xff\xff\xd0\x16\x00\x00\x5b\x7c\xff\xff\xff\xec\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x54\xef\xbf\xd7\x94";
- arg.alock.oh.n_len = 8;
- arg.alock.oh.n_bytes = "\x00\x00\x02\xff\xff\xff\xd3";
- arg.alock.svid = 0x5678;
- arg.alock.l_offset = 0;
- arg.alock.l_len = 100;
-
- res_block.stat.stat = nlm_granted;
- res_block.cookie.n_bytes = "hello";
- res_block.cookie.n_len = 5;
+ CLIENT *cli;
+ nlm_res res_block;
+ nlm_res *out;
+ nlm_lockargs arg;
+ struct timeval tim;
+
+ printf("Creating client for host %s\n", argv[1]);
+ cli = clnt_create(argv[1], NLM_PROG, NLM_VERS, "udp");
+ if (!cli) {
+ errx(1, "Failed to create client\n");
+ /* NOTREACHED */
+ }
+ clnt_control(cli, CLGET_TIMEOUT, &tim);
+ printf("Default timeout was %d.%d\n", tim.tv_sec, tim.tv_usec);
+ tim.tv_usec = -1;
+ tim.tv_sec = -1;
+ clnt_control(cli, CLSET_TIMEOUT, &tim);
+ clnt_control(cli, CLGET_TIMEOUT, &tim);
+ printf("timeout now %d.%d\n", tim.tv_sec, tim.tv_usec);
+
+
+ arg.cookie.n_len = 4;
+ arg.cookie.n_bytes = "hello";
+ arg.block = 0;
+ arg.exclusive = 0;
+ arg.reclaim = 0;
+ arg.state = 0x1234;
+ arg.alock.caller_name = "localhost";
+ arg.alock.fh.n_len = 32;
+ arg.alock.fh.n_bytes = "\x04\x04\x02\x00\x01\x00\x00\x00\x0c\x00\x00\x00\xff\xff\xff\xd0\x16\x00\x00\x5b\x7c\xff\xff\xff\xec\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x54\xef\xbf\xd7\x94";
+ arg.alock.oh.n_len = 8;
+ arg.alock.oh.n_bytes = "\x00\x00\x02\xff\xff\xff\xd3";
+ arg.alock.svid = 0x5678;
+ arg.alock.l_offset = 0;
+ arg.alock.l_len = 100;
+
+ res_block.stat.stat = nlm_granted;
+ res_block.cookie.n_bytes = "hello";
+ res_block.cookie.n_len = 5;
#if 0
- if (nlm_lock_res_1(&res_block, cli)) printf("Success!\n");
- else printf("Fail\n");
+ if (nlm_lock_res_1(&res_block, cli))
+ printf("Success!\n");
+ else
+ printf("Fail\n");
#else
- if (out = nlm_lock_msg_1(&arg, cli))
- {
- printf("Success!\n");
- printf("out->stat = %d", out->stat);
- }
- else
- {
- printf("Fail\n");
- }
+ if (out = nlm_lock_msg_1(&arg, cli)) {
+ printf("Success!\n");
+ printf("out->stat = %d", out->stat);
+ } else {
+ printf("Fail\n");
+ }
#endif
- return 0;
+ return 0;
}
diff --git a/usr.sbin/rpc.statd/statd.h b/usr.sbin/rpc.statd/statd.h
index 7b4e6598adae..7bf7b1d0cc92 100644
--- a/usr.sbin/rpc.statd/statd.h
+++ b/usr.sbin/rpc.statd/statd.h
@@ -29,26 +29,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $FreeBSD$
*/
#include "sm_inter.h"
-/* These pieces are missing from the distributed sm_inter.x, which */
-/* omits the SM_NOTIFY procedure used between cooperating rpc.statd's */
-
-#define SM_NOTIFY ((u_long)6)
-extern void *sm_notify_1();
-
-struct stat_chge
-{
- char *mon_name;
- int state;
-};
-typedef struct stat_chge stat_chge;
-bool_t xdr_stat_chge();
-
/* ------------------------------------------------------------------------- */
/*
Data structures for recording monitored hosts
diff --git a/usr.sbin/rpc.umntall/rpc.umntall.c b/usr.sbin/rpc.umntall/rpc.umntall.c
index c59c77606ffd..5129ba9033d1 100644
--- a/usr.sbin/rpc.umntall/rpc.umntall.c
+++ b/usr.sbin/rpc.umntall/rpc.umntall.c
@@ -171,28 +171,23 @@ main(int argc, char **argv) {
int
do_umntall(char *hostname) {
enum clnt_stat clnt_stat;
- struct hostent *hp;
- struct sockaddr_in saddr;
- struct timeval pertry, try;
- int so;
+ struct addrinfo *ai, hints;
+ struct timeval try;
+ int so, ecode;
CLIENT *clp;
- if ((hp = gethostbyname(hostname)) == NULL) {
- warnx("gethostbyname(%s) failed", hostname);
- return (0);
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_NUMERICHOST;
+ ecode = getaddrinfo(hostname, NULL, &hints, &ai);
+ if (ecode != 0) {
+ warnx("can't get net id for host/nfs: %s",
+ gai_strerror(ecode));
+ return (1);
}
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
- memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
- sizeof(saddr.sin_addr)));
- pertry.tv_sec = 3;
- pertry.tv_usec = 0;
- so = RPC_ANYSOCK;
- if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
- pertry, &so)) == NULL) {
- clnt_pcreateerror("Cannot send MNT PRC");
- return (0);
+ clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
+ if (clp == NULL) {
+ clnt_pcreateerror("Cannot MNT PRC");
+ return (1);
}
clp->cl_auth = authunix_create_default();
try.tv_sec = 3;
@@ -212,30 +207,25 @@ do_umntall(char *hostname) {
int
do_umount(char *hostname, char *dirp) {
enum clnt_stat clnt_stat;
- struct hostent *hp;
- struct sockaddr_in saddr;
- struct timeval pertry, try;
+ struct addrinfo *ai, hints;
+ struct timeval try;
CLIENT *clp;
- int so;
+ int so, ecode;
- if ((hp = gethostbyname(hostname)) == NULL) {
- warnx("gethostbyname(%s) failed", hostname);
- return (0);
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_NUMERICHOST;
+ ecode = getaddrinfo(hostname, NULL, &hints, &ai);
+ if (ecode != 0) {
+ warnx("can't get net id for host/nfs: %s",
+ gai_strerror(ecode));
+ return (1);
}
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
- memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
- sizeof(saddr.sin_addr)));
- pertry.tv_sec = 3;
- pertry.tv_usec = 0;
- so = RPC_ANYSOCK;
- if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
- pertry, &so)) == NULL) {
- clnt_pcreateerror("Cannot send MNT PRC");
- return (0);
+ clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
+ if (clp == NULL) {
+ clnt_pcreateerror("Cannot MNT PRC");
+ return (1);
}
- clp->cl_auth = authunix_create_default();
+ clp->cl_auth = authsys_create_default();
try.tv_sec = 3;
try.tv_usec = 0;
clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp,
diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c
index 03b48250dbda..51f962180ff0 100644
--- a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c
+++ b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c
@@ -298,7 +298,18 @@ the %s domain -- aborting", yppasswd_domain);
}
unlink(sockname);
- transp = svcunix_create(sock, 0, 0, sockname);
+ if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS,
+ "netpath") == 0) {
+ (void) fprintf(stderr,
+ "%s: unable to create service\n", argv[0]);
+ exit(1);
+ }
+ if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG,
+ MASTER_YPPASSWDVERS, "netpath") == 0) {
+ (void) fprintf(stderr,
+ "%s: unable to create service\n", argv[0]);
+ exit(1);
+ }
if (transp == NULL) {
yp_error("cannot create AF_LOCAL service.");
exit(1);
diff --git a/usr.sbin/rpc.ypupdated/ypupdated_extern.h b/usr.sbin/rpc.ypupdated/ypupdated_extern.h
index 28ea7ac30411..17e9ee9cdc60 100644
--- a/usr.sbin/rpc.ypupdated/ypupdated_extern.h
+++ b/usr.sbin/rpc.ypupdated/ypupdated_extern.h
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
#include <db.h>
#define YPOP_CHANGE 1 /* change, do not add */
diff --git a/usr.sbin/rpc.ypupdated/ypupdated_server.c b/usr.sbin/rpc.ypupdated/ypupdated_server.c
index f0c5bff89af5..b306268485ac 100644
--- a/usr.sbin/rpc.ypupdated/ypupdated_server.c
+++ b/usr.sbin/rpc.ypupdated/ypupdated_server.c
@@ -43,7 +43,6 @@ static const char rcsid[] =
#include <stdio.h>
#include <rpc/rpc.h>
-#include <rpc/auth_des.h>
#include <rpc/key_prot.h>
#include <sys/param.h>
#include <sys/cdefs.h>
diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile
new file mode 100644
index 000000000000..fb73b23a0f24
--- /dev/null
+++ b/usr.sbin/rpcbind/Makefile
@@ -0,0 +1,21 @@
+# $NetBSD: Makefile,v 1.3 2000/06/20 13:56:43 fvdl Exp $
+# $FreeBSD$
+
+PROG= rpcbind
+CFLAGS+= -I${LIBCRPCDIR} -I${LIBCINCLUDE} -DPORTMAP -DINET6 -DLIBWRAP
+MAN8= rpcbind.8
+SRCS= check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \
+ rpcb_svc.c rpcb_svc_com.c security.c warmstart.c util.c \
+ rpc_generic.c
+
+LIBCDIR= ${.CURDIR}/../../lib/libc
+LIBCRPCDIR= ${LIBCDIR}/rpc
+LIBCINCLUDE= ${LIBCDIR}/include
+
+
+LDADD+= -lwrap -lutil
+DPADD+= ${LIBWRAP} ${LIBUTIL}
+
+.PATH: ${LIBCRPCDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/rpcbind/check_bound.c b/usr.sbin/rpcbind/check_bound.c
new file mode 100644
index 000000000000..fe503d74ebd6
--- /dev/null
+++ b/usr.sbin/rpcbind/check_bound.c
@@ -0,0 +1,229 @@
+/* $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)check_bound.c 1.15 93/07/05 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
+#endif
+#endif
+
+/*
+ * check_bound.c
+ * Checks to see whether the program is still bound to the
+ * claimed address and returns the univeral merged address
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "rpcbind.h"
+
+struct fdlist {
+ int fd;
+ struct netconfig *nconf;
+ struct fdlist *next;
+ int check_binding;
+};
+
+static struct fdlist *fdhead; /* Link list of the check fd's */
+static struct fdlist *fdtail;
+static char *nullstring = "";
+
+static bool_t check_bound __P((struct fdlist *, char *uaddr));
+
+/*
+ * Returns 1 if the given address is bound for the given addr & transport
+ * For all error cases, we assume that the address is bound
+ * Returns 0 for success.
+ */
+static bool_t
+check_bound(struct fdlist *fdl, char *uaddr)
+{
+ int fd;
+ struct netbuf *na;
+ int ans;
+
+ if (fdl->check_binding == FALSE)
+ return (TRUE);
+
+ na = uaddr2taddr(fdl->nconf, uaddr);
+ if (!na)
+ return (TRUE); /* punt, should never happen */
+
+ fd = __rpc_nconf2fd(fdl->nconf);
+ if (fd < 0) {
+ free(na);
+ return (TRUE);
+ }
+
+ ans = bind(fd, (struct sockaddr *)na->buf, na->len);
+
+ close(fd);
+ free(na);
+
+ return (ans == 0 ? FALSE : TRUE);
+}
+
+int
+add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
+{
+ struct fdlist *fdl;
+ struct netconfig *newnconf;
+
+ newnconf = getnetconfigent(nconf->nc_netid);
+ if (newnconf == NULL)
+ return (-1);
+ fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
+ if (fdl == NULL) {
+ freenetconfigent(newnconf);
+ syslog(LOG_ERR, "no memory!");
+ return (-1);
+ }
+ fdl->nconf = newnconf;
+ fdl->next = NULL;
+ if (fdhead == NULL) {
+ fdhead = fdl;
+ fdtail = fdl;
+ } else {
+ fdtail->next = fdl;
+ fdtail = fdl;
+ }
+ /* XXX no bound checking for now */
+ fdl->check_binding = FALSE;
+
+ return 0;
+}
+
+bool_t
+is_bound(char *netid, char *uaddr)
+{
+ struct fdlist *fdl;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (TRUE);
+ return (check_bound(fdl, uaddr));
+}
+
+/*
+ * Returns NULL if there was some system error.
+ * Returns "" if the address was not bound, i.e the server crashed.
+ * Returns the merged address otherwise.
+ */
+char *
+mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
+{
+ struct fdlist *fdl;
+ char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (NULL);
+ if (check_bound(fdl, uaddr) == FALSE)
+ /* that server died */
+ return (nullstring);
+ /*
+ * If saddr is not NULL, the remote client may have included the
+ * address by which it contacted us. Use that for the "client" uaddr,
+ * otherwise use the info from the SVCXPRT.
+ */
+ if (saddr != NULL) {
+ c_uaddr = saddr;
+ } else {
+ c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
+ if (c_uaddr == NULL) {
+ syslog(LOG_ERR, "taddr2uaddr failed for %s",
+ fdl->nconf->nc_netid);
+ return (NULL);
+ }
+ allocated_uaddr = c_uaddr;
+ }
+
+#ifdef ND_DEBUG
+ if (debugging) {
+ if (saddr == NULL) {
+ fprintf(stderr, "mergeaddr: client uaddr = %s\n",
+ c_uaddr);
+ } else {
+ fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
+ c_uaddr);
+ }
+ }
+#endif
+ s_uaddr = uaddr;
+ /*
+ * This is all we should need for IP 4 and 6
+ */
+ m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
+ uaddr, m_uaddr);
+#endif
+ if (allocated_uaddr != NULL)
+ free(allocated_uaddr);
+ return (m_uaddr);
+}
+
+/*
+ * Returns a netconf structure from its internal list. This
+ * structure should not be freed.
+ */
+struct netconfig *
+rpcbind_get_conf(char *netid)
+{
+ struct fdlist *fdl;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (NULL);
+ return (fdl->nconf);
+}
diff --git a/usr.sbin/rpcbind/pmap_svc.c b/usr.sbin/rpcbind/pmap_svc.c
new file mode 100644
index 000000000000..b2cedd991aad
--- /dev/null
+++ b/usr.sbin/rpcbind/pmap_svc.c
@@ -0,0 +1,368 @@
+/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro";
+#endif
+#endif
+
+/*
+ * pmap_svc.c
+ * The server procedure for the version 2 portmaper.
+ * All the portmapper related interface from the portmap side.
+ */
+
+#ifdef PORTMAP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/rpcb_prot.h>
+#ifdef RPCBIND_DEBUG
+#include <stdlib.h>
+#endif
+#include "rpcbind.h"
+
+static struct pmaplist *find_service_pmap __P((rpcprog_t, rpcvers_t,
+ rpcprot_t));
+static bool_t pmapproc_change __P((struct svc_req *, SVCXPRT *, u_long));
+static bool_t pmapproc_getport __P((struct svc_req *, SVCXPRT *));
+static bool_t pmapproc_dump __P((struct svc_req *, SVCXPRT *));
+
+/*
+ * Called for all the version 2 inquiries.
+ */
+void
+pmap_service(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc);
+ switch (rqstp->rq_proc) {
+ case PMAPPROC_NULL:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "PMAPPROC_NULL\n");
+#endif
+ check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS);
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) &&
+ debugging) {
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_SET:
+ /*
+ * Set a program, version to port mapping
+ */
+ pmapproc_change(rqstp, xprt, rqstp->rq_proc);
+ break;
+
+ case PMAPPROC_UNSET:
+ /*
+ * Remove a program, version to port mapping.
+ */
+ pmapproc_change(rqstp, xprt, rqstp->rq_proc);
+ break;
+
+ case PMAPPROC_GETPORT:
+ /*
+ * Lookup the mapping for a program, version and return its
+ * port number.
+ */
+ pmapproc_getport(rqstp, xprt);
+ break;
+
+ case PMAPPROC_DUMP:
+ /*
+ * Return the current set of mapped program, version
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "PMAPPROC_DUMP\n");
+#endif
+ pmapproc_dump(rqstp, xprt);
+ break;
+
+ case PMAPPROC_CALLIT:
+ /*
+ * Calls a procedure on the local machine. If the requested
+ * procedure is not registered this procedure does not return
+ * error information!!
+ * This procedure is only supported on rpc/udp and calls via
+ * rpc/udp. It passes null authentication parameters.
+ */
+ rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS);
+ break;
+
+ default:
+ svcerr_noproc(xprt);
+ break;
+ }
+}
+
+/*
+ * returns the item with the given program, version number. If that version
+ * number is not found, it returns the item with that program number, so that
+ * the port number is now returned to the caller. The caller when makes a
+ * call to this program, version number, the call will fail and it will
+ * return with PROGVERS_MISMATCH. The user can then determine the highest
+ * and the lowest version number for this program using clnt_geterr() and
+ * use those program version numbers.
+ */
+static struct pmaplist *
+find_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
+{
+ register struct pmaplist *hit = NULL;
+ register struct pmaplist *pml;
+
+ for (pml = list_pml; pml != NULL; pml = pml->pml_next) {
+ if ((pml->pml_map.pm_prog != prog) ||
+ (pml->pml_map.pm_prot != prot))
+ continue;
+ hit = pml;
+ if (pml->pml_map.pm_vers == vers)
+ break;
+ }
+ return (hit);
+}
+
+static bool_t
+pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op)
+{
+ struct pmap reg;
+ RPCB rpcbreg;
+ long ans;
+ struct sockaddr_in *who;
+ struct cmsgcred *cmcred;
+ char uidbuf[32];
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "%s request for (%lu, %lu) : ",
+ op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET",
+ reg.pm_prog, reg.pm_vers);
+#endif
+
+ if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
+ svcerr_decode(xprt);
+ return (FALSE);
+ }
+
+ if (!check_access(xprt, op, &reg, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ return FALSE;
+ }
+
+ who = svc_getcaller(xprt);
+ cmcred = __svc_getcallercreds(xprt);
+
+ /*
+ * Can't use getpwnam here. We might end up calling ourselves
+ * and looping.
+ */
+ if (cmcred == NULL)
+ rpcbreg.r_owner = "unknown";
+ else if (cmcred->cmcred_uid == 0)
+ rpcbreg.r_owner = "superuser";
+ else {
+ /* r_owner will be strdup-ed later */
+ snprintf(uidbuf, sizeof uidbuf, "%d", cmcred->cmcred_uid);
+ rpcbreg.r_owner = uidbuf;
+ }
+
+ rpcbreg.r_prog = reg.pm_prog;
+ rpcbreg.r_vers = reg.pm_vers;
+
+ if (op == PMAPPROC_SET) {
+ char buf[32];
+
+ sprintf(buf, "0.0.0.0.%d.%d", (int)((reg.pm_port >> 8) & 0xff),
+ (int)(reg.pm_port & 0xff));
+ rpcbreg.r_addr = buf;
+ if (reg.pm_prot == IPPROTO_UDP) {
+ rpcbreg.r_netid = udptrans;
+ } else if (reg.pm_prot == IPPROTO_TCP) {
+ rpcbreg.r_netid = tcptrans;
+ } else {
+ ans = FALSE;
+ goto done_change;
+ }
+ ans = map_set(&rpcbreg, rpcbreg.r_owner);
+ } else if (op == PMAPPROC_UNSET) {
+ bool_t ans1, ans2;
+
+ rpcbreg.r_addr = NULL;
+ rpcbreg.r_netid = tcptrans;
+ ans1 = map_unset(&rpcbreg, rpcbreg.r_owner);
+ rpcbreg.r_netid = udptrans;
+ ans2 = map_unset(&rpcbreg, rpcbreg.r_owner);
+ ans = ans1 || ans2;
+ } else {
+ ans = FALSE;
+ }
+done_change:
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) &&
+ debugging) {
+ fprintf(stderr, "portmap: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
+#endif
+ if (op == PMAPPROC_SET)
+ rpcbs_set(RPCBVERS_2_STAT, ans);
+ else
+ rpcbs_unset(RPCBVERS_2_STAT, ans);
+ return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+pmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ struct pmap reg;
+ long lport;
+ int port = 0;
+ struct pmaplist *fnd;
+#ifdef RPCBIND_DEBUG
+ char *uaddr;
+#endif
+
+ if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
+ svcerr_decode(xprt);
+ return (FALSE);
+ }
+
+ if (!check_access(xprt, PMAPPROC_GETPORT, &reg, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ return FALSE;
+ }
+
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid),
+ svc_getrpccaller(xprt));
+ fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :",
+ reg.pm_prog, reg.pm_vers,
+ reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr);
+ free(uaddr);
+ }
+#endif
+ fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd) {
+ char serveuaddr[32], *ua;
+ int h1, h2, h3, h4, p1, p2;
+ char *netid;
+
+ if (reg.pm_prot == IPPROTO_UDP) {
+ ua = udp_uaddr;
+ netid = udptrans;
+ } else {
+ ua = tcp_uaddr; /* To get the len */
+ netid = tcptrans;
+ }
+ if (ua == NULL) {
+ goto sendreply;
+ }
+ if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3,
+ &h4, &p1, &p2) == 6) {
+ p1 = (fnd->pml_map.pm_port >> 8) & 0xff;
+ p2 = (fnd->pml_map.pm_port) & 0xff;
+ sprintf(serveuaddr, "%d.%d.%d.%d.%d.%d",
+ h1, h2, h3, h4, p1, p2);
+ if (is_bound(netid, serveuaddr)) {
+ port = fnd->pml_map.pm_port;
+ } else { /* this service is dead; delete it */
+ delete_prog(reg.pm_prog);
+ }
+ }
+ }
+sendreply:
+ lport = port;
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) &&
+ debugging) {
+ (void) fprintf(stderr, "portmap: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "port = %d\n", port);
+#endif
+ rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers,
+ reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans,
+ port ? udptrans : "");
+
+ return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+pmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) {
+ svcerr_decode(xprt);
+ return (FALSE);
+ }
+
+ if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ return FALSE;
+ }
+
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr,
+ (caddr_t)&list_pml)) && debugging) {
+ if (debugging)
+ (void) fprintf(stderr, "portmap: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ return (TRUE);
+}
+
+#endif /* PORTMAP */
diff --git a/usr.sbin/rpcbind/rpcb_stat.c b/usr.sbin/rpcbind/rpcb_stat.c
new file mode 100644
index 000000000000..05554932ebd0
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcb_stat.c
@@ -0,0 +1,208 @@
+/*
+ * $NetBSD: rpcb_stat.c,v 1.2 2000/07/04 20:27:40 matt Exp $
+ * $FreeBSD$
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* #pragma ident "@(#)rpcb_stat.c 1.7 94/04/25 SMI" */
+
+/*
+ * rpcb_stat.c
+ * Allows for gathering of statistics
+ *
+ * Copyright (c) 1990 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <netconfig.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <sys/stat.h>
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "rpcbind.h"
+
+static rpcb_stat_byvers inf;
+
+void
+rpcbs_init()
+{
+
+}
+
+void
+rpcbs_procinfo(rpcvers_t rtype, rpcproc_t proc)
+{
+ switch (rtype + 2) {
+#ifdef PORTMAP
+ case PMAPVERS: /* version 2 */
+ if (proc > rpcb_highproc_2)
+ return;
+ break;
+#endif
+ case RPCBVERS: /* version 3 */
+ if (proc > rpcb_highproc_3)
+ return;
+ break;
+ case RPCBVERS4: /* version 4 */
+ if (proc > rpcb_highproc_4)
+ return;
+ break;
+ default: return;
+ }
+ inf[rtype].info[proc]++;
+ return;
+}
+
+void
+rpcbs_set(rpcvers_t rtype, bool_t success)
+{
+ if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
+ return;
+ inf[rtype].setinfo++;
+ return;
+}
+
+void
+rpcbs_unset(rpcvers_t rtype, bool_t success)
+{
+ if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
+ return;
+ inf[rtype].unsetinfo++;
+ return;
+}
+
+void
+rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers, char *netid,
+ char *uaddr)
+{
+ rpcbs_addrlist *al;
+ struct netconfig *nconf;
+
+ if (rtype >= RPCBVERS_STAT)
+ return;
+ for (al = inf[rtype].addrinfo; al; al = al->next) {
+
+ if(al->netid == NULL)
+ return;
+ if ((al->prog == prog) && (al->vers == vers) &&
+ (strcmp(al->netid, netid) == 0)) {
+ if ((uaddr == NULL) || (uaddr[0] == NULL))
+ al->failure++;
+ else
+ al->success++;
+ return;
+ }
+ }
+ nconf = rpcbind_get_conf(netid);
+ if (nconf == NULL) {
+ return;
+ }
+ al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist));
+ if (al == NULL) {
+ return;
+ }
+ al->prog = prog;
+ al->vers = vers;
+ al->netid = nconf->nc_netid;
+ if ((uaddr == NULL) || (uaddr[0] == NULL)) {
+ al->failure = 1;
+ al->success = 0;
+ } else {
+ al->failure = 0;
+ al->success = 1;
+ }
+ al->next = inf[rtype].addrinfo;
+ inf[rtype].addrinfo = al;
+}
+
+void
+rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog,
+ rpcvers_t vers, rpcproc_t proc, char *netid, rpcblist_ptr rbl)
+{
+ rpcbs_rmtcalllist *rl;
+ struct netconfig *nconf;
+
+ if (rtype > RPCBVERS_STAT)
+ return;
+ for (rl = inf[rtype].rmtinfo; rl; rl = rl->next) {
+
+ if(rl->netid == NULL)
+ return;
+
+ if ((rl->prog == prog) && (rl->vers == vers) &&
+ (rl->proc == proc) &&
+ (strcmp(rl->netid, netid) == 0)) {
+ if ((rbl == NULL) ||
+ (rbl->rpcb_map.r_vers != vers))
+ rl->failure++;
+ else
+ rl->success++;
+ if (rpcbproc == RPCBPROC_INDIRECT)
+ rl->indirect++;
+ return;
+ }
+ }
+ nconf = rpcbind_get_conf(netid);
+ if (nconf == NULL) {
+ return;
+ }
+ rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist));
+ if (rl == NULL) {
+ return;
+ }
+ rl->prog = prog;
+ rl->vers = vers;
+ rl->proc = proc;
+ rl->netid = nconf->nc_netid;
+ if ((rbl == NULL) ||
+ (rbl->rpcb_map.r_vers != vers)) {
+ rl->failure = 1;
+ rl->success = 0;
+ } else {
+ rl->failure = 0;
+ rl->success = 1;
+ }
+ rl->indirect = 1;
+ rl->next = inf[rtype].rmtinfo;
+ inf[rtype].rmtinfo = rl;
+ return;
+}
+
+/*
+ */
+void *
+rpcbproc_getstat(void *arg, struct svc_req *req, SVCXPRT *xprt,
+ rpcvers_t versnum)
+{
+ return (void *)&inf;
+}
diff --git a/usr.sbin/rpcbind/rpcb_svc.c b/usr.sbin/rpcbind/rpcb_svc.c
new file mode 100644
index 000000000000..b01e9ac4be10
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcb_svc.c
@@ -0,0 +1,233 @@
+/* $NetBSD: rpcb_svc.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcb_svc.c 1.16 93/07/05 SMI" */
+
+/*
+ * rpcb_svc.c
+ * The server procedure for the version 3 rpcbind (TLI).
+ *
+ * It maintains a separate list of all the registered services with the
+ * version 3 of rpcbind.
+ */
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rpcbind.h"
+
+static void *rpcbproc_getaddr_3_local __P((void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t));
+static void *rpcbproc_dump_3_local __P((void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t));
+
+/*
+ * Called by svc_getreqset. There is a separate server handle for
+ * every transport that it waits on.
+ */
+void
+rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ RPCB rpcbproc_set_3_arg;
+ RPCB rpcbproc_unset_3_arg;
+ RPCB rpcbproc_getaddr_3_local_arg;
+ struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
+ char *rpcbproc_uaddr2taddr_3_arg;
+ struct netbuf rpcbproc_taddr2uaddr_3_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ void *(*local) __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+
+ rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_NULL\n");
+#endif
+ /* This call just logs, no actual checks */
+ check_access(transp, rqstp->rq_proc, NULL, RPCBVERS);
+ (void) svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
+ return;
+
+ case RPCBPROC_SET:
+ xdr_argument = (xdrproc_t )xdr_rpcb;
+ xdr_result = (xdrproc_t )xdr_bool;
+ local = rpcbproc_set_com;
+ break;
+
+ case RPCBPROC_UNSET:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_unset_com;
+ break;
+
+ case RPCBPROC_GETADDR:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getaddr_3_local;
+ break;
+
+ case RPCBPROC_DUMP:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_DUMP\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
+ local = rpcbproc_dump_3_local;
+ break;
+
+ case RPCBPROC_CALLIT:
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
+ return;
+
+ case RPCBPROC_GETTIME:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_GETTIME\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_u_long;
+ local = rpcbproc_gettime_com;
+ break;
+
+ case RPCBPROC_UADDR2TADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_wrapstring;
+ xdr_result = (xdrproc_t)xdr_netbuf;
+ local = rpcbproc_uaddr2taddr_com;
+ break;
+
+ case RPCBPROC_TADDR2UADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_netbuf;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_taddr2uaddr_com;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ (void) memset((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
+ (char *) &argument)) {
+ svcerr_decode(transp);
+ if (debugging)
+ (void) fprintf(stderr, "rpcbind: could not decode\n");
+ return;
+ }
+ if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS)) {
+ svcerr_weakauth(transp);
+ goto done;
+ }
+ result = (*local)(&argument, rqstp, transp, RPCBVERS);
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
+ result)) {
+ svcerr_systemerr(transp);
+ if (debugging) {
+ (void) fprintf(stderr, "rpcbind: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+done:
+ if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
+ &argument)) {
+ if (debugging) {
+ (void) fprintf(stderr, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ *
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddr_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t versnum)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
+ RPCB_ALLVERS));
+}
+
+/* ARGSUSED */
+static void *
+rpcbproc_dump_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t versnum)
+{
+ return ((void *)&list_rbl);
+}
diff --git a/usr.sbin/rpcbind/rpcb_svc_4.c b/usr.sbin/rpcbind/rpcb_svc_4.c
new file mode 100644
index 000000000000..5f14474a038e
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcb_svc_4.c
@@ -0,0 +1,454 @@
+/*
+ * $NetBSD: rpcb_svc_4.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $
+ * $FreeBSD$
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcb_svc_4.c 1.8 93/07/05 SMI" */
+
+/*
+ * rpcb_svc_4.c
+ * The server procedure for the version 4 rpcbind.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rpcbind.h"
+
+static void *rpcbproc_getaddr_4_local __P((void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t));
+static void *rpcbproc_getversaddr_4_local __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+static void *rpcbproc_getaddrlist_4_local
+ __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+static void free_rpcb_entry_list __P((rpcb_entry_list_ptr *));
+static void *rpcbproc_dump_4_local __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+
+/*
+ * Called by svc_getreqset. There is a separate server handle for
+ * every transport that it waits on.
+ */
+void
+rpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ rpcb rpcbproc_set_4_arg;
+ rpcb rpcbproc_unset_4_arg;
+ rpcb rpcbproc_getaddr_4_local_arg;
+ char *rpcbproc_uaddr2taddr_4_arg;
+ struct netbuf rpcbproc_taddr2uaddr_4_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ void *(*local) __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+
+ rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_NULL\n");
+#endif
+ check_access(transp, rqstp->rq_proc, NULL, RPCBVERS4);
+ (void) svc_sendreply(transp, (xdrproc_t) xdr_void,
+ (char *)NULL);
+ return;
+
+ case RPCBPROC_SET:
+ /*
+ * Check to see whether the message came from
+ * loopback transports (for security reasons)
+ */
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_set_com;
+ break;
+
+ case RPCBPROC_UNSET:
+ /*
+ * Check to see whether the message came from
+ * loopback transports (for security reasons)
+ */
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_unset_com;
+ break;
+
+ case RPCBPROC_GETADDR:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getaddr_4_local;
+ break;
+
+ case RPCBPROC_GETVERSADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_GETVERSADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getversaddr_4_local;
+ break;
+
+ case RPCBPROC_DUMP:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_DUMP\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
+ local = rpcbproc_dump_4_local;
+ break;
+
+ case RPCBPROC_INDIRECT:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_INDIRECT\n");
+#endif
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
+ return;
+
+/* case RPCBPROC_CALLIT: */
+ case RPCBPROC_BCAST:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_BCAST\n");
+#endif
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
+ return;
+
+ case RPCBPROC_GETTIME:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_GETTIME\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_u_long;
+ local = rpcbproc_gettime_com;
+ break;
+
+ case RPCBPROC_UADDR2TADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_wrapstring;
+ xdr_result = (xdrproc_t)xdr_netbuf;
+ local = rpcbproc_uaddr2taddr_com;
+ break;
+
+ case RPCBPROC_TADDR2UADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_netbuf;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_taddr2uaddr_com;
+ break;
+
+ case RPCBPROC_GETADDRLIST:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_GETADDRLIST\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr;
+ local = rpcbproc_getaddrlist_4_local;
+ break;
+
+ case RPCBPROC_GETSTAT:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCBPROC_GETSTAT\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers;
+ local = rpcbproc_getstat;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ memset((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
+ (char *)&argument)) {
+ svcerr_decode(transp);
+ if (debugging)
+ (void) fprintf(stderr, "rpcbind: could not decode\n");
+ return;
+ }
+ if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS4)) {
+ svcerr_weakauth(transp);
+ goto done;
+ }
+ result = (*local)(&argument, rqstp, transp, RPCBVERS4);
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result,
+ result)) {
+ svcerr_systemerr(transp);
+ if (debugging) {
+ (void) fprintf(stderr, "rpcbind: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+done:
+ if (!svc_freeargs(transp, (xdrproc_t) xdr_argument,
+ (char *)&argument)) {
+ if (debugging) {
+ (void) fprintf(stderr, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ * Even if a service with a different version number is available,
+ * it will return that address. The client should check with an
+ * clnt_call to verify whether the service is the one that is desired.
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
+ RPCB_ALLVERS));
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ *
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getversaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t versnum)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ fprintf(stderr, "RPCB_GETVERSADDR rqst for (%lu, %lu, %s)"
+ " from %s : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
+ RPCB_ONEVERS));
+}
+
+/*
+ * Lookup the mapping for a program, version and return the
+ * addresses for all transports in the current transport family.
+ * We return a merged address.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t versnum)
+{
+ RPCB *regp = (RPCB *)arg;
+ static rpcb_entry_list_ptr rlist;
+ register rpcblist_ptr rbl;
+ rpcb_entry_list_ptr rp, tail;
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcb_entry *a;
+ struct netconfig *nconf;
+ struct netconfig *reg_nconf;
+ char *saddr, *maddr = NULL;
+
+ free_rpcb_entry_list(&rlist);
+ prog = regp->r_prog;
+ vers = regp->r_vers;
+ reg_nconf = rpcbind_get_conf(transp->xp_netid);
+ if (reg_nconf == NULL)
+ return (NULL);
+ if (*(regp->r_addr) != '\0') {
+ saddr = regp->r_addr;
+ } else {
+ saddr = NULL;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ fprintf(stderr, "r_addr: %s r_netid: %s nc_protofmly: %s\n",
+ regp->r_addr, regp->r_netid, reg_nconf->nc_protofmly);
+ }
+#endif
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog == prog) &&
+ (rbl->rpcb_map.r_vers == vers)) {
+ nconf = rpcbind_get_conf(rbl->rpcb_map.r_netid);
+ if (nconf == NULL)
+ goto fail;
+ if (strcmp(nconf->nc_protofmly, reg_nconf->nc_protofmly)
+ != 0) {
+ continue; /* not same proto family */
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "\tmerge with: %s", rbl->rpcb_map.r_addr);
+#endif
+ if ((maddr = mergeaddr(transp, rbl->rpcb_map.r_netid,
+ rbl->rpcb_map.r_addr, saddr)) == NULL) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, " FAILED\n");
+#endif
+ continue;
+ } else if (!maddr[0]) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, " SUCCEEDED, but port died - maddr: nullstring\n");
+#endif
+ /* The server died. Unset this combination */
+ delete_prog(regp->r_prog);
+ continue;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, " SUCCEEDED maddr: %s\n", maddr);
+#endif
+ /*
+ * Add it to rlist.
+ */
+ rp = (rpcb_entry_list_ptr)
+ malloc((u_int)sizeof (rpcb_entry_list));
+ if (rp == NULL)
+ goto fail;
+ a = &rp->rpcb_entry_map;
+ a->r_maddr = maddr;
+ a->r_nc_netid = nconf->nc_netid;
+ a->r_nc_semantics = nconf->nc_semantics;
+ a->r_nc_protofmly = nconf->nc_protofmly;
+ a->r_nc_proto = nconf->nc_proto;
+ rp->rpcb_entry_next = NULL;
+ if (rlist == NULL) {
+ rlist = rp;
+ tail = rp;
+ } else {
+ tail->rpcb_entry_next = rp;
+ tail = rp;
+ }
+ rp = NULL;
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ for (rp = rlist; rp; rp = rp->rpcb_entry_next) {
+ fprintf(stderr, "\t%s %s\n", rp->rpcb_entry_map.r_maddr,
+ rp->rpcb_entry_map.r_nc_proto);
+ }
+ }
+#endif
+ /*
+ * XXX: getaddrlist info is also being stuffed into getaddr.
+ * Perhaps wrong, but better than it not getting counted at all.
+ */
+ rpcbs_getaddr(RPCBVERS4 - 2, prog, vers, transp->xp_netid, maddr);
+ return (void *)&rlist;
+
+fail: free_rpcb_entry_list(&rlist);
+ return (NULL);
+}
+
+/*
+ * Free only the allocated structure, rest is all a pointer to some
+ * other data somewhere else.
+ */
+static void
+free_rpcb_entry_list(rpcb_entry_list_ptr *rlistp)
+{
+ register rpcb_entry_list_ptr rbl, tmp;
+
+ for (rbl = *rlistp; rbl != NULL; ) {
+ tmp = rbl;
+ rbl = rbl->rpcb_entry_next;
+ free((char *)tmp->rpcb_entry_map.r_maddr);
+ free((char *)tmp);
+ }
+ *rlistp = NULL;
+}
+
+/* ARGSUSED */
+static void *
+rpcbproc_dump_4_local(void *arg, struct svc_req *req, SVCXPRT *xprt,
+ rpcvers_t versnum)
+{
+ return ((void *)&list_rbl);
+}
diff --git a/usr.sbin/rpcbind/rpcb_svc_com.c b/usr.sbin/rpcbind/rpcb_svc_com.c
new file mode 100644
index 000000000000..e0c74876afdd
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcb_svc_com.c
@@ -0,0 +1,1457 @@
+/* $NetBSD: rpcb_svc_com.c,v 1.6 2000/08/03 00:07:22 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcb_svc_com.c 1.18 94/05/02 SMI" */
+
+/*
+ * rpcb_svc_com.c
+ * The commom server procedure for the rpcbind.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/svc_dg.h>
+#include <netconfig.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#include <rpc/pmap_prot.h>
+#endif /* PORTMAP */
+#include <string.h>
+#include <stdlib.h>
+
+#include "rpcbind.h"
+
+#define RPC_BUF_MAX 65536 /* can be raised if required */
+
+static char *nullstring = "";
+static int rpcb_rmtcalls;
+
+struct rmtcallfd_list {
+ int fd;
+ SVCXPRT *xprt;
+ char *netid;
+ struct rmtcallfd_list *next;
+};
+
+#define NFORWARD 64
+#define MAXTIME_OFF 300 /* 5 minutes */
+
+struct finfo {
+ int flag;
+#define FINFO_ACTIVE 0x1
+ u_int32_t caller_xid;
+ struct netbuf *caller_addr;
+ u_int32_t forward_xid;
+ int forward_fd;
+ char *uaddr;
+ rpcproc_t reply_type;
+ rpcvers_t versnum;
+ time_t time;
+};
+static struct finfo FINFO[NFORWARD];
+
+
+static bool_t xdr_encap_parms __P((XDR *, struct encap_parms *));
+static bool_t xdr_rmtcall_args __P((XDR *, struct r_rmtcall_args *));
+static bool_t xdr_rmtcall_result __P((XDR *, struct r_rmtcall_args *));
+static bool_t xdr_opaque_parms __P((XDR *, struct r_rmtcall_args *));
+static int find_rmtcallfd_by_netid __P((char *));
+static SVCXPRT *find_rmtcallxprt_by_fd __P((int));
+static u_int32_t forward_register __P((u_int32_t, struct netbuf *, int, char *,
+ rpcproc_t, rpcvers_t));
+static struct finfo *forward_find __P((u_int32_t));
+static int free_slot_by_xid __P((u_int32_t));
+static int free_slot_by_index __P((int));
+static int netbufcmp __P((struct netbuf *, struct netbuf *));
+static struct netbuf *netbufdup __P((struct netbuf *));
+static void netbuffree __P((struct netbuf *));
+static int check_rmtcalls __P((struct pollfd *, int));
+static void xprt_set_caller __P((SVCXPRT *, struct finfo *));
+static void send_svcsyserr __P((SVCXPRT *, struct finfo *));
+static void handle_reply __P((int, SVCXPRT *));
+static void find_versions __P((rpcprog_t, char *, rpcvers_t *, rpcvers_t *));
+static rpcblist_ptr find_service __P((rpcprog_t, rpcvers_t, char *));
+static char *getowner __P((SVCXPRT *, char *, size_t));
+static int add_pmaplist __P((RPCB *));
+static int del_pmaplist __P((RPCB *));
+
+/*
+ * Set a mapping of program, version, netid
+ */
+/* ARGSUSED */
+void *
+rpcbproc_set_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ RPCB *regp = (RPCB *)arg;
+ static bool_t ans;
+ char owner[64];
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCB_SET request for (%lu, %lu, %s, %s) : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, regp->r_addr);
+#endif
+ ans = map_set(regp, getowner(transp, owner, sizeof owner));
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_set(rpcbversnum - 2, ans);
+ return (void *)&ans;
+}
+
+bool_t
+map_set(RPCB *regp, char *owner)
+{
+ RPCB reg, *a;
+ rpcblist_ptr rbl, fnd;
+
+ reg = *regp;
+ /*
+ * check to see if already used
+ * find_service returns a hit even if
+ * the versions don't match, so check for it
+ */
+ fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid);
+ if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) {
+ if (!strcmp(fnd->rpcb_map.r_addr, reg.r_addr))
+ /*
+ * if these match then it is already
+ * registered so just say "OK".
+ */
+ return (TRUE);
+ else
+ return (FALSE);
+ }
+ /*
+ * add to the end of the list
+ */
+ rbl = (rpcblist_ptr) malloc((u_int)sizeof (RPCBLIST));
+ if (rbl == (rpcblist_ptr)NULL) {
+ return (FALSE);
+ }
+ a = &(rbl->rpcb_map);
+ a->r_prog = reg.r_prog;
+ a->r_vers = reg.r_vers;
+ a->r_netid = strdup(reg.r_netid);
+ a->r_addr = strdup(reg.r_addr);
+ a->r_owner = strdup(owner);
+ if (!a->r_addr || !a->r_netid || !a->r_owner) {
+ if (a->r_netid)
+ free((void *) a->r_netid);
+ if (a->r_addr)
+ free((void *) a->r_addr);
+ if (a->r_owner)
+ free((void *) a->r_owner);
+ free((void *)rbl);
+ return (FALSE);
+ }
+ rbl->rpcb_next = (rpcblist_ptr)NULL;
+ if (list_rbl == NULL) {
+ list_rbl = rbl;
+ } else {
+ for (fnd = list_rbl; fnd->rpcb_next;
+ fnd = fnd->rpcb_next)
+ ;
+ fnd->rpcb_next = rbl;
+ }
+#ifdef PORTMAP
+ (void) add_pmaplist(regp);
+#endif
+ return (TRUE);
+}
+
+/*
+ * Unset a mapping of program, version, netid
+ */
+/* ARGSUSED */
+void *
+rpcbproc_unset_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ RPCB *regp = (RPCB *)arg;
+ static bool_t ans;
+ char owner[64];
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "RPCB_UNSET request for (%lu, %lu, %s) : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid);
+#endif
+ ans = map_unset(regp, getowner(transp, owner, sizeof owner));
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_unset(rpcbversnum - 2, ans);
+ return (void *)&ans;
+}
+
+bool_t
+map_unset(RPCB *regp, char *owner)
+{
+ int ans = 0;
+ rpcblist_ptr rbl, prev, tmp;
+
+ if (owner == NULL)
+ return (0);
+
+ for (prev = NULL, rbl = list_rbl; rbl; /* cstyle */) {
+ if ((rbl->rpcb_map.r_prog != regp->r_prog) ||
+ (rbl->rpcb_map.r_vers != regp->r_vers) ||
+ (regp->r_netid[0] && strcasecmp(regp->r_netid,
+ rbl->rpcb_map.r_netid))) {
+ /* both rbl & prev move forwards */
+ prev = rbl;
+ rbl = rbl->rpcb_next;
+ continue;
+ }
+ /*
+ * Check whether appropriate uid. Unset only
+ * if superuser or the owner itself.
+ */
+ if (strcmp(owner, "superuser") &&
+ strcmp(rbl->rpcb_map.r_owner, owner))
+ return (0);
+ /* found it; rbl moves forward, prev stays */
+ ans = 1;
+ tmp = rbl;
+ rbl = rbl->rpcb_next;
+ if (prev == NULL)
+ list_rbl = rbl;
+ else
+ prev->rpcb_next = rbl;
+ free((void *) tmp->rpcb_map.r_addr);
+ free((void *) tmp->rpcb_map.r_netid);
+ free((void *) tmp->rpcb_map.r_owner);
+ free((void *) tmp);
+ }
+#ifdef PORTMAP
+ if (ans)
+ (void) del_pmaplist(regp);
+#endif
+ /*
+ * We return 1 either when the entry was not there or it
+ * was able to unset it. It can come to this point only if
+ * atleast one of the conditions is true.
+ */
+ return (1);
+}
+
+void
+delete_prog(int prog)
+{
+ RPCB reg;
+ register rpcblist_ptr rbl;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog))
+ continue;
+ if (is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr))
+ continue;
+ reg.r_prog = rbl->rpcb_map.r_prog;
+ reg.r_vers = rbl->rpcb_map.r_vers;
+ reg.r_netid = strdup(rbl->rpcb_map.r_netid);
+ (void) map_unset(&reg, "superuser");
+ free(reg.r_netid);
+ }
+}
+
+void *
+rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum, rpcvers_t verstype)
+{
+ static char *uaddr;
+ char *saddr = NULL;
+ rpcblist_ptr fnd;
+
+ if (uaddr && uaddr[0])
+ free((void *) uaddr);
+ fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid);
+ if (fnd && ((verstype == RPCB_ALLVERS) ||
+ (regp->r_vers == fnd->rpcb_map.r_vers))) {
+ if (*(regp->r_addr) != '\0') { /* may contain a hint about */
+ saddr = regp->r_addr; /* the interface that we */
+ } /* should use */
+ if (!(uaddr = mergeaddr(transp, transp->xp_netid,
+ fnd->rpcb_map.r_addr, saddr))) {
+ /* Try whatever we have */
+ uaddr = strdup(fnd->rpcb_map.r_addr);
+ } else if (!uaddr[0]) {
+ /*
+ * The server died. Unset all versions of this prog.
+ */
+ delete_prog(regp->r_prog);
+ uaddr = nullstring;
+ }
+ } else {
+ uaddr = nullstring;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "getaddr: %s\n", uaddr);
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers,
+ transp->xp_netid, uaddr);
+ return (void *)&uaddr;
+}
+
+/* ARGSUSED */
+void *
+rpcbproc_gettime_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ static time_t curtime;
+
+ (void) time(&curtime);
+ return (void *)&curtime;
+}
+
+/*
+ * Convert uaddr to taddr. Should be used only by
+ * local servers/clients. (kernel level stuff only)
+ */
+/* ARGSUSED */
+void *
+rpcbproc_uaddr2taddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ char **uaddrp = (char **)arg;
+ struct netconfig *nconf;
+ static struct netbuf nbuf;
+ static struct netbuf *taddr;
+
+ if (taddr) {
+ free((void *) taddr->buf);
+ free((void *) taddr);
+ }
+ if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
+ ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) {
+ (void) memset((char *)&nbuf, 0, sizeof (struct netbuf));
+ return (void *)&nbuf;
+ }
+ return (void *)taddr;
+}
+
+/*
+ * Convert taddr to uaddr. Should be used only by
+ * local servers/clients. (kernel level stuff only)
+ */
+/* ARGSUSED */
+void *
+rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ struct netbuf *taddr = (struct netbuf *)arg;
+ static char *uaddr;
+ struct netconfig *nconf;
+
+#ifdef CHEW_FDS
+ int fd;
+
+ if ((fd = open("/dev/null", O_RDONLY)) == -1) {
+ uaddr = (char *)strerror(errno);
+ return (&uaddr);
+ }
+#endif /* CHEW_FDS */
+ if (uaddr && !uaddr[0])
+ free((void *) uaddr);
+ if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
+ ((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) {
+ uaddr = nullstring;
+ }
+ return (void *)&uaddr;
+}
+
+
+static bool_t
+xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
+{
+ return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), ~0));
+}
+
+/*
+ * XDR remote call arguments. It ignores the address part.
+ * written for XDR_DECODE direction only
+ */
+static bool_t
+xdr_rmtcall_args(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ /* does not get the address or the arguments */
+ if (xdr_u_int32_t(xdrs, &(cap->rmt_prog)) &&
+ xdr_u_int32_t(xdrs, &(cap->rmt_vers)) &&
+ xdr_u_int32_t(xdrs, &(cap->rmt_proc))) {
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR remote call results along with the address. Ignore
+ * program number, version number and proc number.
+ * Written for XDR_ENCODE direction only.
+ */
+static bool_t
+xdr_rmtcall_result(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ bool_t result;
+
+#ifdef PORTMAP
+ if (cap->rmt_localvers == PMAPVERS) {
+ int h1, h2, h3, h4, p1, p2;
+ u_long port;
+
+ /* interpret the universal address for TCP/IP */
+ if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d",
+ &h1, &h2, &h3, &h4, &p1, &p2) != 6)
+ return (FALSE);
+ port = ((p1 & 0xff) << 8) + (p2 & 0xff);
+ result = xdr_u_long(xdrs, &port);
+ } else
+#endif
+ if ((cap->rmt_localvers == RPCBVERS) ||
+ (cap->rmt_localvers == RPCBVERS4)) {
+ result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr));
+ } else {
+ return (FALSE);
+ }
+ if (result == TRUE)
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct r_rmtcall_args.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+static struct rmtcallfd_list *rmthead;
+static struct rmtcallfd_list *rmttail;
+
+int
+create_rmtcall_fd(struct netconfig *nconf)
+{
+ int fd;
+ struct rmtcallfd_list *rmt;
+ SVCXPRT *xprt;
+
+ if ((fd = __rpc_nconf2fd(nconf)) == -1) {
+ if (debugging)
+ fprintf(stderr,
+ "create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n",
+ nconf->nc_device, errno);
+ return (-1);
+ }
+ xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0);
+ if (xprt == NULL) {
+ if (debugging)
+ fprintf(stderr,
+ "create_rmtcall_fd: svc_tli_create failed\n");
+ return (-1);
+ }
+ rmt = (struct rmtcallfd_list *)malloc((u_int)
+ sizeof (struct rmtcallfd_list));
+ if (rmt == NULL) {
+ syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
+ return (-1);
+ }
+ rmt->xprt = xprt;
+ rmt->netid = strdup(nconf->nc_netid);
+ xprt->xp_netid = rmt->netid;
+ rmt->fd = fd;
+ rmt->next = NULL;
+ if (rmthead == NULL) {
+ rmthead = rmt;
+ rmttail = rmt;
+ } else {
+ rmttail->next = rmt;
+ rmttail = rmt;
+ }
+ /* XXX not threadsafe */
+ if (fd > svc_maxfd)
+ svc_maxfd = fd;
+ FD_SET(fd, &svc_fdset);
+ return (fd);
+}
+
+static int
+find_rmtcallfd_by_netid(char *netid)
+{
+ struct rmtcallfd_list *rmt;
+
+ for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
+ if (strcmp(netid, rmt->netid) == 0) {
+ return (rmt->fd);
+ }
+ }
+ return (-1);
+}
+
+static SVCXPRT *
+find_rmtcallxprt_by_fd(int fd)
+{
+ struct rmtcallfd_list *rmt;
+
+ for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
+ if (fd == rmt->fd) {
+ return (rmt->xprt);
+ }
+ }
+ return (NULL);
+}
+
+
+/*
+ * Call a remote procedure service. This procedure is very quiet when things
+ * go wrong. The proc is written to support broadcast rpc. In the broadcast
+ * case, a machine should shut-up instead of complain, lest the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply.
+ * When receiving a request and verifying that the service exists, we
+ *
+ * receive the request
+ *
+ * open a new TLI endpoint on the same transport on which we received
+ * the original request
+ *
+ * remember the original request's XID (which requires knowing the format
+ * of the svc_dg_data structure)
+ *
+ * forward the request, with a new XID, to the requested service,
+ * remembering the XID used to send this request (for later use in
+ * reassociating the answer with the original request), the requestor's
+ * address, the file descriptor on which the forwarded request is
+ * made and the service's address.
+ *
+ * mark the file descriptor on which we anticipate receiving a reply from
+ * the service and one to select for in our private svc_run procedure
+ *
+ * At some time in the future, a reply will be received from the service to
+ * which we forwarded the request. At that time, we detect that the socket
+ * used was for forwarding (by looking through the finfo structures to see
+ * whether the fd corresponds to one of those) and call handle_reply() to
+ *
+ * receive the reply
+ *
+ * bundle the reply, along with the service's universal address
+ *
+ * create a SVCXPRT structure and use a version of svc_sendreply
+ * that allows us to specify the reply XID and destination, send the reply
+ * to the original requestor.
+ */
+
+void
+rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp,
+ rpcproc_t reply_type, rpcvers_t versnum)
+{
+ register rpcblist_ptr rbl;
+ struct netconfig *nconf;
+ struct netbuf *caller;
+ struct r_rmtcall_args a;
+ char *buf_alloc = NULL, *outbufp;
+ char *outbuf_alloc = NULL;
+ char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX];
+ struct netbuf *na = (struct netbuf *) NULL;
+ struct rpc_msg call_msg;
+ int outlen;
+ u_int sendsz;
+ XDR outxdr;
+ AUTH *auth;
+ int fd = -1;
+ char *uaddr, *m_uaddr, *local_uaddr = NULL;
+ u_int32_t *xidp;
+ struct __rpc_sockinfo si;
+ struct sockaddr *localsa;
+ struct netbuf tbuf;
+
+ if (!__rpc_fd2sockinfo(transp->xp_fd, &si)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ return;
+ }
+ if (si.si_socktype != SOCK_DGRAM)
+ return; /* Only datagram type accepted */
+ sendsz = __rpc_get_t_size(si.si_af, si.si_proto, UDPMSGSIZE);
+ if (sendsz == 0) { /* data transfer not supported */
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ return;
+ }
+ /*
+ * Should be multiple of 4 for XDR.
+ */
+ sendsz = ((sendsz + 3) / 4) * 4;
+ if (sendsz > RPC_BUF_MAX) {
+#ifdef notyet
+ buf_alloc = alloca(sendsz); /* not in IDR2? */
+#else
+ buf_alloc = malloc(sendsz);
+#endif /* notyet */
+ if (buf_alloc == NULL) {
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: No Memory!\n");
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ return;
+ }
+ a.rmt_args.args = buf_alloc;
+ } else {
+ a.rmt_args.args = buf;
+ }
+
+ call_msg.rm_xid = 0; /* For error checking purposes */
+ if (!svc_getargs(transp, (xdrproc_t) xdr_rmtcall_args, (char *) &a)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_decode(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: svc_getargs failed\n");
+ goto error;
+ }
+
+ if (!check_callit(transp, &a, versnum)) {
+ svcerr_weakauth(transp);
+ goto error;
+ }
+
+ caller = svc_getrpccaller(transp);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller);
+ fprintf(stderr, "%s %s req for (%lu, %lu, %lu, %s) from %s : ",
+ versnum == PMAPVERS ? "pmap_rmtcall" :
+ versnum == RPCBVERS ? "rpcb_rmtcall" :
+ versnum == RPCBVERS4 ? "rpcb_indirect" : "unknown",
+ reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit",
+ (unsigned long)a.rmt_prog, (unsigned long)a.rmt_vers,
+ (unsigned long)a.rmt_proc, transp->xp_netid,
+ uaddr ? uaddr : "unknown");
+ if (uaddr)
+ free((void *) uaddr);
+ }
+#endif
+
+ rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid);
+
+ rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers,
+ a.rmt_proc, transp->xp_netid, rbl);
+
+ if (rbl == (rpcblist_ptr)NULL) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "not found\n");
+#endif
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_noprog(transp);
+ goto error;
+ }
+ if (rbl->rpcb_map.r_vers != a.rmt_vers) {
+ if (reply_type == RPCBPROC_INDIRECT) {
+ rpcvers_t vers_low, vers_high;
+
+ find_versions(a.rmt_prog, transp->xp_netid,
+ &vers_low, &vers_high);
+ svcerr_progvers(transp, vers_low, vers_high);
+ }
+ goto error;
+ }
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr);
+#endif
+ /*
+ * Check whether this entry is valid and a server is present
+ * Mergeaddr() returns NULL if no such entry is present, and
+ * returns "" if the entry was present but the server is not
+ * present (i.e., it crashed).
+ */
+ if (reply_type == RPCBPROC_INDIRECT) {
+ uaddr = mergeaddr(transp, transp->xp_netid,
+ rbl->rpcb_map.r_addr, NULL);
+ if ((uaddr == (char *) NULL) || uaddr[0] == '\0') {
+ svcerr_noprog(transp);
+ if (uaddr != NULL) {
+ free((void *) uaddr);
+ }
+ goto error;
+ }
+ if (uaddr != NULL) {
+ free((void *) uaddr);
+ }
+ }
+ nconf = rpcbind_get_conf(transp->xp_netid);
+ if (nconf == (struct netconfig *)NULL) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: rpcbind_get_conf failed\n");
+ goto error;
+ }
+ localsa = local_sa(((struct sockaddr *)caller->buf)->sa_family);
+ if (localsa == NULL) {
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: no local address\n");
+ goto error;
+ }
+ tbuf.len = tbuf.maxlen = localsa->sa_len;
+ tbuf.buf = localsa;
+ local_uaddr =
+ addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, nconf->nc_netid);
+ m_uaddr = addrmerge(caller, rbl->rpcb_map.r_addr, NULL,
+ nconf->nc_netid);
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ fprintf(stderr, "merged uaddr %s\n", m_uaddr);
+#endif
+ if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ free((void *) m_uaddr);
+ goto error;
+ }
+ xidp = __rpcb_get_dg_xidp(transp);
+ call_msg.rm_xid = forward_register(*xidp,
+ caller, fd, m_uaddr, reply_type, versnum);
+ if (call_msg.rm_xid == 0) {
+ /*
+ * A duplicate request for the slow server. Let's not
+ * beat on it any more.
+ */
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: duplicate request\n");
+ free((void *) m_uaddr);
+ goto error;
+ } else if (call_msg.rm_xid == -1) {
+ /* forward_register failed. Perhaps no memory. */
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: forward_register failed\n");
+ free((void *) m_uaddr);
+ goto error;
+ }
+
+#ifdef DEBUG_RMTCALL
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: original XID %x, new XID %x\n",
+ *xidp, call_msg.rm_xid);
+#endif
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = a.rmt_prog;
+ call_msg.rm_call.cb_vers = a.rmt_vers;
+ if (sendsz > RPC_BUF_MAX) {
+#ifdef notyet
+ outbuf_alloc = alloca(sendsz); /* not in IDR2? */
+#else
+ outbuf_alloc = malloc(sendsz);
+#endif /* notyet */
+ if (outbuf_alloc == NULL) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: No memory!\n");
+ goto error;
+ }
+ xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE);
+ } else {
+ xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE);
+ }
+ if (!xdr_callhdr(&outxdr, &call_msg)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: xdr_callhdr failed\n");
+ goto error;
+ }
+ if (!xdr_u_int32_t(&outxdr, &(a.rmt_proc))) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: xdr_u_long failed\n");
+ goto error;
+ }
+
+ if (rqstp->rq_cred.oa_flavor == AUTH_NULL) {
+ auth = authnone_create();
+ } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
+ struct authunix_parms *au;
+
+ au = (struct authunix_parms *)rqstp->rq_clntcred;
+ auth = authunix_create(au->aup_machname,
+ au->aup_uid, au->aup_gid,
+ au->aup_len, au->aup_gids);
+ if (auth == NULL) /* fall back */
+ auth = authnone_create();
+ } else {
+ /* we do not support any other authentication scheme */
+ if (debugging)
+ fprintf(stderr,
+"rpcbproc_callit_com: oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n");
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_weakauth(transp); /* XXX too strong.. */
+ goto error;
+ }
+ if (auth == NULL) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: authwhatever_create returned NULL\n");
+ goto error;
+ }
+ if (!AUTH_MARSHALL(auth, &outxdr)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ AUTH_DESTROY(auth);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
+ goto error;
+ }
+ AUTH_DESTROY(auth);
+ if (!xdr_opaque_parms(&outxdr, &a)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: xdr_opaque_parms failed\n");
+ goto error;
+ }
+ outlen = (int) XDR_GETPOS(&outxdr);
+ if (outbuf_alloc)
+ outbufp = outbuf_alloc;
+ else
+ outbufp = outbuf;
+
+ na = uaddr2taddr(nconf, local_uaddr);
+ if (!na) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ goto error;
+ }
+
+ if (sendto(fd, outbufp, outlen, 0, (struct sockaddr *)na->buf, na->len)
+ != outlen) {
+ if (debugging)
+ fprintf(stderr,
+ "rpcbproc_callit_com: sendto failed: errno %d\n", errno);
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ goto error;
+ }
+ goto out;
+
+error:
+ if (call_msg.rm_xid != 0)
+ (void) free_slot_by_xid(call_msg.rm_xid);
+out:
+ if (local_uaddr)
+ free(local_uaddr);
+ if (buf_alloc)
+ free((void *) buf_alloc);
+ if (outbuf_alloc)
+ free((void *) outbuf_alloc);
+ if (na) {
+ free(na->buf);
+ free(na);
+ }
+}
+
+/*
+ * Makes an entry into the FIFO for the given request.
+ * If duplicate request, returns a 0, else returns the xid of its call.
+ */
+static u_int32_t
+forward_register(u_int32_t caller_xid, struct netbuf *caller_addr,
+ int forward_fd, char *uaddr, rpcproc_t reply_type,
+ rpcvers_t versnum)
+{
+ int i;
+ int j = 0;
+ time_t min_time, time_now;
+ static u_int32_t lastxid;
+ int entry = -1;
+
+ min_time = FINFO[0].time;
+ time_now = time((time_t *)0);
+ /* initialization */
+ if (lastxid == 0)
+ lastxid = time_now * NFORWARD;
+
+ /*
+ * Check if it is an duplicate entry. Then,
+ * try to find an empty slot. If not available, then
+ * use the slot with the earliest time.
+ */
+ for (i = 0; i < NFORWARD; i++) {
+ if (FINFO[i].flag & FINFO_ACTIVE) {
+ if ((FINFO[i].caller_xid == caller_xid) &&
+ (FINFO[i].reply_type == reply_type) &&
+ (FINFO[i].versnum == versnum) &&
+ (!netbufcmp(FINFO[i].caller_addr,
+ caller_addr))) {
+ FINFO[i].time = time((time_t *)0);
+ return (0); /* Duplicate entry */
+ } else {
+ /* Should we wait any longer */
+ if ((time_now - FINFO[i].time) > MAXTIME_OFF)
+ (void) free_slot_by_index(i);
+ }
+ }
+ if (entry == -1) {
+ if ((FINFO[i].flag & FINFO_ACTIVE) == 0) {
+ entry = i;
+ } else if (FINFO[i].time < min_time) {
+ j = i;
+ min_time = FINFO[i].time;
+ }
+ }
+ }
+ if (entry != -1) {
+ /* use this empty slot */
+ j = entry;
+ } else {
+ (void) free_slot_by_index(j);
+ }
+ if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) {
+ return (-1);
+ }
+ rpcb_rmtcalls++; /* no of pending calls */
+ FINFO[j].flag = FINFO_ACTIVE;
+ FINFO[j].reply_type = reply_type;
+ FINFO[j].versnum = versnum;
+ FINFO[j].time = time_now;
+ FINFO[j].caller_xid = caller_xid;
+ FINFO[j].forward_fd = forward_fd;
+ /*
+ * Though uaddr is not allocated here, it will still be freed
+ * from free_slot_*().
+ */
+ FINFO[j].uaddr = uaddr;
+ lastxid = lastxid + NFORWARD;
+ FINFO[j].forward_xid = lastxid + j; /* encode slot */
+ return (FINFO[j].forward_xid); /* forward on this xid */
+}
+
+static struct finfo *
+forward_find(u_int32_t reply_xid)
+{
+ int i;
+
+ i = reply_xid % NFORWARD;
+ if (i < 0)
+ i += NFORWARD;
+ if ((FINFO[i].flag & FINFO_ACTIVE) &&
+ (FINFO[i].forward_xid == reply_xid)) {
+ return (&FINFO[i]);
+ }
+ return (NULL);
+}
+
+static int
+free_slot_by_xid(u_int32_t xid)
+{
+ int entry;
+
+ entry = xid % NFORWARD;
+ if (entry < 0)
+ entry += NFORWARD;
+ return (free_slot_by_index(entry));
+}
+
+static int
+free_slot_by_index(int index)
+{
+ struct finfo *fi;
+
+ fi = &FINFO[index];
+ if (fi->flag & FINFO_ACTIVE) {
+ netbuffree(fi->caller_addr);
+ /* XXX may be too big, but can't access xprt array here */
+ if (fi->forward_fd >= svc_maxfd)
+ svc_maxfd--;
+ free((void *) fi->uaddr);
+ fi->flag &= ~FINFO_ACTIVE;
+ rpcb_rmtcalls--;
+ return (1);
+ }
+ return (0);
+}
+
+static int
+netbufcmp(struct netbuf *n1, struct netbuf *n2)
+{
+ return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len));
+}
+
+static struct netbuf *
+netbufdup(struct netbuf *ap)
+{
+ struct netbuf *np;
+
+ np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len);
+ if (np) {
+ np->maxlen = np->len = ap->len;
+ np->buf = ((char *) np) + sizeof (struct netbuf);
+ (void) memcpy(np->buf, ap->buf, ap->len);
+ }
+ return (np);
+}
+
+static void
+netbuffree(struct netbuf *ap)
+{
+ free((void *) ap);
+}
+
+
+#define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
+
+void
+my_svc_run()
+{
+ size_t nfds;
+ struct pollfd pollfds[FD_SETSIZE];
+ int poll_ret, check_ret;
+ int n;
+#ifdef SVC_RUN_DEBUG
+ int i;
+#endif
+ register struct pollfd *p;
+
+ for (;;) {
+ p = pollfds;
+ for (n = 0; n <= svc_maxfd; n++) {
+ if (FD_ISSET(n, &svc_fdset)) {
+ p->fd = n;
+ p->events = MASKVAL;
+ p++;
+ }
+ }
+ nfds = p - pollfds;
+ poll_ret = 0;
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ fprintf(stderr, "polling for read on fd < ");
+ for (i = 0, p = pollfds; i < nfds; i++, p++)
+ if (p->events)
+ fprintf(stderr, "%d ", p->fd);
+ fprintf(stderr, ">\n");
+ }
+#endif
+ switch (poll_ret = poll(pollfds, nfds, INFTIM)) {
+ case -1:
+ /*
+ * We ignore all errors, continuing with the assumption
+ * that it was set by the signal handlers (or any
+ * other outside event) and not caused by poll().
+ */
+ case 0:
+ continue;
+ default:
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ fprintf(stderr, "poll returned read fds < ");
+ for (i = 0, p = pollfds; i < nfds; i++, p++)
+ if (p->revents)
+ fprintf(stderr, "%d ", p->fd);
+ fprintf(stderr, ">\n");
+ }
+#endif
+ /*
+ * If we found as many replies on callback fds
+ * as the number of descriptors selectable which
+ * poll() returned, there can be no more so we
+ * don't call svc_getreq_poll. Otherwise, there
+ * must be another so we must call svc_getreq_poll.
+ */
+ if ((check_ret = check_rmtcalls(pollfds, nfds)) ==
+ poll_ret)
+ continue;
+ svc_getreq_poll(pollfds, poll_ret-check_ret);
+ }
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ fprintf(stderr, "svc_maxfd now %u\n", svc_maxfd);
+ }
+#endif
+ }
+}
+
+static int
+check_rmtcalls(struct pollfd *pfds, int nfds)
+{
+ int j, ncallbacks_found = 0, rmtcalls_pending;
+ SVCXPRT *xprt;
+
+ if (rpcb_rmtcalls == 0)
+ return (0);
+
+ rmtcalls_pending = rpcb_rmtcalls;
+ for (j = 0; j < nfds; j++) {
+ if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) {
+ if (pfds[j].revents) {
+ ncallbacks_found++;
+#ifdef DEBUG_RMTCALL
+ if (debugging)
+ fprintf(stderr,
+"my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n",
+ pfds[j].fd, xprt->xp_netid);
+#endif
+ handle_reply(pfds[j].fd, xprt);
+ pfds[j].revents = 0;
+ if (ncallbacks_found >= rmtcalls_pending) {
+ break;
+ }
+ }
+ }
+ }
+ return (ncallbacks_found);
+}
+
+static void
+xprt_set_caller(SVCXPRT *xprt, struct finfo *fi)
+{
+ u_int32_t *xidp;
+
+ *(svc_getrpccaller(xprt)) = *(fi->caller_addr);
+ xidp = __rpcb_get_dg_xidp(xprt);
+ *xidp = fi->caller_xid;
+}
+
+/*
+ * Call svcerr_systemerr() only if RPCBVERS4
+ */
+static void
+send_svcsyserr(SVCXPRT *xprt, struct finfo *fi)
+{
+ if (fi->reply_type == RPCBPROC_INDIRECT) {
+ xprt_set_caller(xprt, fi);
+ svcerr_systemerr(xprt);
+ }
+ return;
+}
+
+static void
+handle_reply(int fd, SVCXPRT *xprt)
+{
+ XDR reply_xdrs;
+ struct rpc_msg reply_msg;
+ struct rpc_err reply_error;
+ char *buffer;
+ struct finfo *fi;
+ int inlen, pos, len;
+ struct r_rmtcall_args a;
+ struct sockaddr_storage ss;
+ socklen_t fromlen;
+#ifdef SVC_RUN_DEBUG
+ char *uaddr;
+#endif
+
+ buffer = malloc(RPC_BUF_MAX);
+ if (buffer == NULL)
+ goto done;
+
+ do {
+ inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0,
+ (struct sockaddr *)&ss, &fromlen);
+ } while (inlen < 0 && errno == EINTR);
+ if (inlen < 0) {
+ if (debugging)
+ fprintf(stderr,
+ "handle_reply: recvfrom returned %d, errno %d\n", inlen, errno);
+ goto done;
+ }
+
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = 0;
+ reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+
+ xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE);
+ if (!xdr_replymsg(&reply_xdrs, &reply_msg)) {
+ if (debugging)
+ (void) fprintf(stderr,
+ "handle_reply: xdr_replymsg failed\n");
+ goto done;
+ }
+ fi = forward_find(reply_msg.rm_xid);
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ fprintf(stderr, "handle_reply: reply xid: %d fi addr: %p\n",
+ reply_msg.rm_xid, fi);
+ }
+#endif
+ if (fi == NULL) {
+ goto done;
+ }
+ _seterr_reply(&reply_msg, &reply_error);
+ if (reply_error.re_status != RPC_SUCCESS) {
+ if (debugging)
+ (void) fprintf(stderr, "handle_reply: %s\n",
+ clnt_sperrno(reply_error.re_status));
+ send_svcsyserr(xprt, fi);
+ goto done;
+ }
+ pos = XDR_GETPOS(&reply_xdrs);
+ len = inlen - pos;
+ a.rmt_args.args = &buffer[pos];
+ a.rmt_args.arglen = len;
+ a.rmt_uaddr = fi->uaddr;
+ a.rmt_localvers = fi->versnum;
+
+ xprt_set_caller(xprt, fi);
+#ifdef SVC_RUN_DEBUG
+ uaddr = taddr2uaddr(rpcbind_get_conf("udp"),
+ svc_getrpccaller(xprt));
+ if (debugging) {
+ fprintf(stderr, "handle_reply: forwarding address %s to %s\n",
+ a.rmt_uaddr, uaddr ? uaddr : "unknown");
+ }
+ if (uaddr)
+ free((void *) uaddr);
+#endif
+ svc_sendreply(xprt, (xdrproc_t) xdr_rmtcall_result, (char *) &a);
+done:
+ if (buffer)
+ free(buffer);
+
+ if (reply_msg.rm_xid == 0) {
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ fprintf(stderr, "handle_reply: NULL xid on exit!\n");
+ }
+#endif
+ } else
+ (void) free_slot_by_xid(reply_msg.rm_xid);
+ return;
+}
+
+static void
+find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp)
+{
+ register rpcblist_ptr rbl;
+ int lowv = 0;
+ int highv = 0;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog) ||
+ ((rbl->rpcb_map.r_netid != NULL) &&
+ (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
+ continue;
+ if (lowv == 0) {
+ highv = rbl->rpcb_map.r_vers;
+ lowv = highv;
+ } else if (rbl->rpcb_map.r_vers < lowv) {
+ lowv = rbl->rpcb_map.r_vers;
+ } else if (rbl->rpcb_map.r_vers > highv) {
+ highv = rbl->rpcb_map.r_vers;
+ }
+ }
+ *lowvp = lowv;
+ *highvp = highv;
+ return;
+}
+
+/*
+ * returns the item with the given program, version number and netid.
+ * If that version number is not found, it returns the item with that
+ * program number, so that address is now returned to the caller. The
+ * caller when makes a call to this program, version number, the call
+ * will fail and it will return with PROGVERS_MISMATCH. The user can
+ * then determine the highest and the lowest version number for this
+ * program using clnt_geterr() and use those program version numbers.
+ *
+ * Returns the RPCBLIST for the given prog, vers and netid
+ */
+static rpcblist_ptr
+find_service(rpcprog_t prog, rpcvers_t vers, char *netid)
+{
+ register rpcblist_ptr hit = NULL;
+ register rpcblist_ptr rbl;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog) ||
+ ((rbl->rpcb_map.r_netid != NULL) &&
+ (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
+ continue;
+ hit = rbl;
+ if (rbl->rpcb_map.r_vers == vers)
+ break;
+ }
+ return (hit);
+}
+
+/*
+ * Copies the name associated with the uid of the caller and returns
+ * a pointer to it. Similar to getwd().
+ */
+static char *
+getowner(SVCXPRT *transp, char *owner, size_t ownersize)
+{
+ struct cmsgcred *cmcred;
+
+ cmcred = __svc_getcallercreds(transp);
+ if (cmcred == NULL)
+ strlcpy(owner, "unknown", ownersize);
+ else if (cmcred->cmcred_uid == 0)
+ strlcpy(owner, "superuser", ownersize);
+ else
+ snprintf(owner, ownersize, "%d", cmcred->cmcred_uid);
+
+ return owner;
+}
+
+#ifdef PORTMAP
+/*
+ * Add this to the pmap list only if it is UDP or TCP.
+ */
+static int
+add_pmaplist(RPCB *arg)
+{
+ struct pmap pmap;
+ struct pmaplist *pml;
+ int h1, h2, h3, h4, p1, p2;
+
+ if (strcmp(arg->r_netid, udptrans) == 0) {
+ /* It is UDP! */
+ pmap.pm_prot = IPPROTO_UDP;
+ } else if (strcmp(arg->r_netid, tcptrans) == 0) {
+ /* It is TCP */
+ pmap.pm_prot = IPPROTO_TCP;
+ } else
+ /* Not a IP protocol */
+ return (0);
+
+ /* interpret the universal address for TCP/IP */
+ if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d",
+ &h1, &h2, &h3, &h4, &p1, &p2) != 6)
+ return (0);
+ pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff);
+ pmap.pm_prog = arg->r_prog;
+ pmap.pm_vers = arg->r_vers;
+ /*
+ * add to END of list
+ */
+ pml = (struct pmaplist *) malloc((u_int)sizeof (struct pmaplist));
+ if (pml == NULL) {
+ (void) syslog(LOG_ERR, "rpcbind: no memory!\n");
+ return (1);
+ }
+ pml->pml_map = pmap;
+ pml->pml_next = NULL;
+ if (list_pml == NULL) {
+ list_pml = pml;
+ } else {
+ struct pmaplist *fnd;
+
+ /* Attach to the end of the list */
+ for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next)
+ ;
+ fnd->pml_next = pml;
+ }
+ return (0);
+}
+
+/*
+ * Delete this from the pmap list only if it is UDP or TCP.
+ */
+static int
+del_pmaplist(RPCB *arg)
+{
+ struct pmaplist *pml;
+ struct pmaplist *prevpml, *fnd;
+ long prot;
+
+ if (strcmp(arg->r_netid, udptrans) == 0) {
+ /* It is UDP! */
+ prot = IPPROTO_UDP;
+ } else if (strcmp(arg->r_netid, tcptrans) == 0) {
+ /* It is TCP */
+ prot = IPPROTO_TCP;
+ } else if (arg->r_netid[0] == NULL) {
+ prot = 0; /* Remove all occurrences */
+ } else {
+ /* Not a IP protocol */
+ return (0);
+ }
+ for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) {
+ if ((pml->pml_map.pm_prog != arg->r_prog) ||
+ (pml->pml_map.pm_vers != arg->r_vers) ||
+ (prot && (pml->pml_map.pm_prot != prot))) {
+ /* both pml & prevpml move forwards */
+ prevpml = pml;
+ pml = pml->pml_next;
+ continue;
+ }
+ /* found it; pml moves forward, prevpml stays */
+ fnd = pml;
+ pml = pml->pml_next;
+ if (prevpml == NULL)
+ list_pml = pml;
+ else
+ prevpml->pml_next = pml;
+ free((void *) fnd);
+ }
+ return (0);
+}
+#endif /* PORTMAP */
diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8
new file mode 100644
index 000000000000..34fea3df9f4f
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcbind.8
@@ -0,0 +1,112 @@
+.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $FreeBSD$
+.Dd September 14, 1992
+.Dt RPCBIND 8
+.Os
+.Sh NAME
+.Nm rpcbind
+.Nd universal addresses to RPC program number mapper
+.Sh SYNOPSIS
+.Nm
+.Op Fl dilLs
+.Sh DESCRIPTION
+.Nm
+is a server that converts
+.Tn RPC
+program numbers into
+universal addresses.
+It must be running on the host to be able to make
+.Tn RPC
+calls
+on a server on that machine.
+.Pp
+When an
+.Tn RPC
+service is started,
+it tells
+.Nm
+the address at which it is listening,
+and the
+.Tn RPC
+program numbers it is prepared to serve.
+When a client wishes to make an
+.Tn RPC
+call to a given program number,
+it first contacts
+.Nm
+on the server machine to determine
+the address where
+.Tn RPC
+requests should be sent.
+.Pp
+.Nm
+should be started before any other RPC service.
+Normally, standard
+.Tn RPC
+servers are started by port monitors, so
+.Nm
+must be started before port monitors are invoked.
+.Pp
+When
+.Nm
+is started, it checks that certain name-to-address
+translation-calls function correctly.
+If they fail, the network configuration databases may be corrupt.
+Since
+.Tn RPC
+services cannot function correctly in this situation,
+.Nm
+reports the condition and terminates.
+.Pp
+.Nm
+can only be started by the super-user.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl d
+Run in debug mode.
+In this mode,
+.Nm
+will not fork when it starts, will print additional information
+during operation, and will abort on certain errors.
+With this option, the name-to-address translation consistency
+checks are shown in detail.
+.It Fl i
+.Dq insecure
+mode.
+Allows calls to SET and UNSET from any host.
+Normally
+.Nm
+accepts these requests only from the loopback interface for security reasons.
+This change is necessary for programs that were compiled with earlier
+versions of the rpc library and do not make those requests using the
+loopback interface.
+.It Fl l
+Turns on libwrap connection logging.
+.It Fl s
+causes
+.Nm
+to change to the user daemon as soon as possible.
+This causes
+.Nm
+to use non-privileged ports for outgoing connections, preventing non-privileged
+clients from using
+.Nm
+to connect to services from a privileged port.
+.It Fl L
+Allow old-style local connections over the loopback interface.
+Without this flag, local connections are only allowed over a local socket,
+.Pa /var/run/rpcbind.sock
+.El
+.Sh NOTES
+All RPC servers must be restarted if
+.Nm
+is restarted.
+.Sh SEE ALSO
+.Xr rpcbind 3 ,
+.Xr rpcinfo 8
+.Sh FILES
+.Bl -tag -width /var/run/rpcbind.sock -compact
+.It Pa /var/run/rpcbind.sock
+.El
diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c
new file mode 100644
index 000000000000..2ddf2c084f8d
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcbind.c
@@ -0,0 +1,568 @@
+/* $NetBSD: rpcbind.c,v 1.1 2000/06/02 23:15:42 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcbind.c 1.19 94/04/25 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro";
+#endif
+#endif
+
+/*
+ * rpcbind.c
+ * Implements the program, version to address mapping for rpc.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <rpc/rpc.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#endif
+#include <netdb.h>
+#include <stdio.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <err.h>
+#include <libutil.h>
+#include <pwd.h>
+#include <string.h>
+#include <errno.h>
+#include "rpcbind.h"
+
+/* Global variables */
+int debugging = 0; /* Tell me what's going on */
+int doabort = 0; /* When debugging, do an abort on errors */
+rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
+
+/* who to suid to if -s is given */
+#define RUN_AS "daemon"
+
+int runasdaemon = 0;
+int insecure = 0;
+int oldstyle_local = 0;
+int verboselog = 0;
+
+#ifdef WARMSTART
+/* Local Variable */
+static int warmstart = 0; /* Grab a old copy of registrations */
+#endif
+
+#ifdef PORTMAP
+struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
+char *udptrans; /* Name of UDP transport */
+char *tcptrans; /* Name of TCP transport */
+char *udp_uaddr; /* Universal UDP address */
+char *tcp_uaddr; /* Universal TCP address */
+#endif
+static char servname[] = "rpcbind";
+static char superuser[] = "superuser";
+
+int main __P((int, char *[]));
+
+static int init_transport __P((struct netconfig *));
+static void rbllist_add __P((rpcprog_t, rpcvers_t, struct netconfig *,
+ struct netbuf *));
+static void terminate __P((int));
+static void parseargs __P((int, char *[]));
+
+int
+main(int argc, char *argv[])
+{
+ struct netconfig *nconf;
+ void *nc_handle; /* Net config handle */
+ struct rlimit rl;
+
+ parseargs(argc, argv);
+
+ getrlimit(RLIMIT_NOFILE, &rl);
+ if (rl.rlim_cur < 128) {
+ if (rl.rlim_max <= 128)
+ rl.rlim_cur = rl.rlim_max;
+ else
+ rl.rlim_cur = 128;
+ setrlimit(RLIMIT_NOFILE, &rl);
+ }
+ openlog("rpcbind", LOG_CONS, LOG_DAEMON);
+ if (geteuid()) { /* This command allowed only to root */
+ fprintf(stderr, "Sorry. You are not superuser\n");
+ exit(1);
+ }
+ nc_handle = setnetconfig(); /* open netconfig file */
+ if (nc_handle == NULL) {
+ syslog(LOG_ERR, "could not read /etc/netconfig");
+ exit(1);
+ }
+#ifdef PORTMAP
+ udptrans = "";
+ tcptrans = "";
+#endif
+
+ nconf = getnetconfigent("unix");
+ if (nconf == NULL) {
+ syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
+ exit(1);
+ }
+ init_transport(nconf);
+
+ while ((nconf = getnetconfig(nc_handle))) {
+ if (nconf->nc_flag & NC_VISIBLE)
+ init_transport(nconf);
+ }
+ endnetconfig(nc_handle);
+
+ /* catch the usual termination signals for graceful exit */
+ (void) signal(SIGCHLD, reap);
+ (void) signal(SIGINT, terminate);
+ (void) signal(SIGTERM, terminate);
+ (void) signal(SIGQUIT, terminate);
+ /* ignore others that could get sent */
+ (void) signal(SIGPIPE, SIG_IGN);
+ (void) signal(SIGHUP, SIG_IGN);
+ (void) signal(SIGUSR1, SIG_IGN);
+ (void) signal(SIGUSR2, SIG_IGN);
+#ifdef WARMSTART
+ if (warmstart) {
+ read_warmstart();
+ }
+#endif
+ if (debugging) {
+ printf("rpcbind debugging enabled.");
+ if (doabort) {
+ printf(" Will abort on errors!\n");
+ } else {
+ printf("\n");
+ }
+ } else {
+ if (daemon(0, 0))
+ err(1, "fork failed");
+ }
+
+ if (runasdaemon) {
+ struct passwd *p;
+
+ if((p = getpwnam(RUN_AS)) == NULL) {
+ syslog(LOG_ERR, "cannot get uid of daemon: %m");
+ exit(1);
+ }
+ if (setuid(p->pw_uid) == -1) {
+ syslog(LOG_ERR, "setuid to daemon failed: %m");
+ exit(1);
+ }
+ }
+
+ network_init();
+
+ my_svc_run();
+ syslog(LOG_ERR, "svc_run returned unexpectedly");
+ rpcbind_abort();
+ /* NOTREACHED */
+
+ return 0;
+}
+
+/*
+ * Adds the entry into the rpcbind database.
+ * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
+ * Returns 0 if succeeds, else fails
+ */
+static int
+init_transport(struct netconfig *nconf)
+{
+ int fd;
+ struct t_bind taddr;
+ struct addrinfo hints, *res = NULL;
+ struct __rpc_sockinfo si;
+ SVCXPRT *my_xprt;
+ int status; /* bound checking ? */
+ int aicode;
+ int addrlen;
+ struct sockaddr *sa;
+ struct sockaddr_un sun;
+ mode_t oldmask;
+
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ return (1); /* not my type */
+#ifdef ND_DEBUG
+ if (debugging) {
+ int i;
+ char **s;
+
+ (void) fprintf(stderr, "%s: %ld lookup routines :\n",
+ nconf->nc_netid, nconf->nc_nlookups);
+ for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
+ i++, s++)
+ fprintf(stderr, "[%d] - %s\n", i, *s);
+ }
+#endif
+
+ /*
+ * XXX - using RPC library internal functions.
+ */
+ if ((fd = __rpc_nconf2fd(nconf)) < 0) {
+ syslog(LOG_ERR, "cannot create socket for %s", nconf->nc_netid);
+ return (1);
+ }
+
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ syslog(LOG_ERR, "cannot get information for %s",
+ nconf->nc_netid);
+ return (1);
+ }
+
+ if (!strcmp(nconf->nc_netid, "unix")) {
+ memset(&sun, 0, sizeof sun);
+ sun.sun_family = AF_LOCAL;
+ unlink(_PATH_RPCBINDSOCK);
+ strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+ sun.sun_len = SUN_LEN(&sun);
+ addrlen = sizeof (struct sockaddr_un);
+ sa = (struct sockaddr *)&sun;
+ } else {
+ /* Get rpcbind's address on this transport */
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = si.si_af;
+ hints.ai_socktype = si.si_socktype;
+ hints.ai_protocol = si.si_proto;
+ if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
+ syslog(LOG_ERR, "cannot get local address for %s: %s",
+ nconf->nc_netid, gai_strerror(aicode));
+ return 1;
+ }
+ addrlen = res->ai_addrlen;
+ sa = (struct sockaddr *)res->ai_addr;
+ }
+ oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+ if (bind(fd, sa, addrlen) < 0) {
+ syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ (void) umask(oldmask);
+
+ /* Copy the address */
+ taddr.addr.len = taddr.addr.maxlen = addrlen;
+ taddr.addr.buf = malloc(addrlen);
+ if (taddr.addr.buf == NULL) {
+ syslog(LOG_ERR, "cannot allocate memory for %s address",
+ nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ memcpy(taddr.addr.buf, sa, addrlen);
+#ifdef ND_DEBUG
+ if (debugging) {
+ /* for debugging print out our universal address */
+ char *uaddr;
+ struct netbuf nb;
+
+ nb.buf = sa;
+ nb.len = nb.maxlen = sa->sa_len;
+ uaddr = taddr2uaddr(nconf, &nb);
+ (void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr);
+ (void) free(uaddr);
+ }
+#endif
+
+ if (res != NULL)
+ freeaddrinfo(res);
+
+ if (nconf->nc_semantics != NC_TPI_CLTS)
+ listen(fd, SOMAXCONN);
+
+ my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 0, 0);
+ if (my_xprt == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "%s: could not create service",
+ nconf->nc_netid);
+ goto error;
+ }
+
+#ifdef PORTMAP
+ /*
+ * Register both the versions for tcp/ip, udp/ip and local.
+ */
+ if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
+ (strcmp(nconf->nc_proto, NC_TCP) == 0 ||
+ strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
+ strcmp(nconf->nc_netid, "unix") == 0) {
+ struct pmaplist *pml;
+
+ if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
+ pmap_service, NULL)) {
+ syslog(LOG_ERR, "could not register on %s",
+ nconf->nc_netid);
+ goto error;
+ }
+ pml = (struct pmaplist *)malloc((u_int)sizeof (struct pmaplist));
+ if (pml == (struct pmaplist *)NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_port = PMAPPORT;
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ if (tcptrans[0]) {
+ syslog(LOG_ERR,
+ "cannot have more than one TCP transport");
+ goto error;
+ }
+ tcptrans = strdup(nconf->nc_netid);
+ pml->pml_map.pm_prot = IPPROTO_TCP;
+
+ /* Let's snarf the universal address */
+ /* "h1.h2.h3.h4.p1.p2" */
+ tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
+ } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
+ if (udptrans[0]) {
+ syslog(LOG_ERR,
+ "cannot have more than one UDP transport");
+ goto error;
+ }
+ udptrans = strdup(nconf->nc_netid);
+ pml->pml_map.pm_prot = IPPROTO_UDP;
+
+ /* Let's snarf the universal address */
+ /* "h1.h2.h3.h4.p1.p2" */
+ udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
+ } else if (strcmp(nconf->nc_netid, "unix") == 0)
+ pml->pml_map.pm_prot = IPPROTO_ST;
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Add version 3 information */
+ pml = (struct pmaplist *)malloc((u_int)sizeof (struct pmaplist));
+ if (pml == (struct pmaplist *)NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map = list_pml->pml_map;
+ pml->pml_map.pm_vers = RPCBVERS;
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Add version 4 information */
+ pml = (struct pmaplist *)malloc((u_int)sizeof (struct pmaplist));
+ if (pml == (struct pmaplist *)NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map = list_pml->pml_map;
+ pml->pml_map.pm_vers = RPCBVERS4;
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Also add version 2 stuff to rpcbind list */
+ rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
+ }
+#endif
+
+ /* version 3 registration */
+ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
+ syslog(LOG_ERR, "could not register %s version 3",
+ nconf->nc_netid);
+ goto error;
+ }
+ rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
+
+ /* version 4 registration */
+ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
+ syslog(LOG_ERR, "could not register %s version 4",
+ nconf->nc_netid);
+ goto error;
+ }
+ rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
+
+ /* decide if bound checking works for this transport */
+ status = add_bndlist(nconf, &taddr.addr);
+#ifdef BIND_DEBUG
+ if (debugging) {
+ if (status < 0) {
+ fprintf(stderr, "Error in finding bind status for %s\n",
+ nconf->nc_netid);
+ } else if (status == 0) {
+ fprintf(stderr, "check binding for %s\n",
+ nconf->nc_netid);
+ } else if (status > 0) {
+ fprintf(stderr, "No check binding for %s\n",
+ nconf->nc_netid);
+ }
+ }
+#endif
+ /*
+ * rmtcall only supported on CLTS transports for now.
+ */
+ if (nconf->nc_semantics == NC_TPI_CLTS) {
+ status = create_rmtcall_fd(nconf);
+
+#ifdef BIND_DEBUG
+ if (debugging) {
+ if (status < 0) {
+ fprintf(stderr,
+ "Could not create rmtcall fd for %s\n",
+ nconf->nc_netid);
+ } else {
+ fprintf(stderr, "rmtcall fd for %s is %d\n",
+ nconf->nc_netid, status);
+ }
+ }
+#endif
+ }
+ return (0);
+error:
+ close(fd);
+ return (1);
+}
+
+static void
+rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
+ struct netbuf *addr)
+{
+ rpcblist_ptr rbl;
+
+ rbl = (rpcblist_ptr)malloc((u_int)sizeof (rpcblist));
+ if (rbl == (rpcblist_ptr)NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+
+ rbl->rpcb_map.r_prog = prog;
+ rbl->rpcb_map.r_vers = vers;
+ rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
+ rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
+ rbl->rpcb_map.r_owner = strdup(superuser);
+ rbl->rpcb_next = list_rbl; /* Attach to global list */
+ list_rbl = rbl;
+}
+
+/*
+ * Catch the signal and die
+ */
+static void
+terminate(int dummy)
+{
+#ifdef WARMSTART
+ syslog(LOG_ERR,
+ "rpcbind terminating on signal. Restart with \"rpcbind -w\"");
+ write_warmstart(); /* Dump yourself */
+#endif
+ exit(2);
+}
+
+void
+rpcbind_abort()
+{
+#ifdef WARMSTART
+ write_warmstart(); /* Dump yourself */
+#endif
+ abort();
+}
+
+/* get command line options */
+static void
+parseargs(int argc, char *argv[])
+{
+ int c;
+
+ while ((c = getopt(argc, argv, "dwailLs")) != -1) {
+ switch (c) {
+ case 'a':
+ doabort = 1; /* when debugging, do an abort on */
+ break; /* errors; for rpcbind developers */
+ /* only! */
+ case 'd':
+ debugging = 1;
+ break;
+ case 'i':
+ insecure = 1;
+ break;
+ case 'L':
+ oldstyle_local = 1;
+ break;
+ case 'l':
+ verboselog = 1;
+ break;
+ case 's':
+ runasdaemon = 1;
+ break;
+#ifdef WARMSTART
+ case 'w':
+ warmstart = 1;
+ break;
+#endif
+ default: /* error */
+ fprintf(stderr, "usage: rpcbind [-Idwils]\n");
+ exit (1);
+ }
+ }
+ if (doabort && !debugging) {
+ fprintf(stderr,
+ "-a (abort) specified without -d (debugging) -- ignored.\n");
+ doabort = 0;
+ }
+}
+
+void
+reap(int dummy)
+{
+ int save_errno = errno;
+
+ while (wait3(NULL, WNOHANG, NULL) > 0)
+ ;
+ errno = save_errno;
+}
+
+void
+toggle_verboselog(int dummy)
+{
+ verboselog = !verboselog;
+}
diff --git a/usr.sbin/rpcbind/rpcbind.h b/usr.sbin/rpcbind/rpcbind.h
new file mode 100644
index 000000000000..63cf2d4200f5
--- /dev/null
+++ b/usr.sbin/rpcbind/rpcbind.h
@@ -0,0 +1,144 @@
+/* $NetBSD: rpcbind.h,v 1.1 2000/06/03 00:47:21 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)rpcbind.h 1.4 90/04/12 SMI" */
+
+/*
+ * rpcbind.h
+ * The common header declarations
+ */
+
+#ifndef rpcbind_h
+#define rpcbind_h
+
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#endif
+#include <rpc/rpcb_prot.h>
+
+/*
+ * Stuff for the rmtcall service
+ */
+struct encap_parms {
+ u_int32_t arglen;
+ char *args;
+};
+
+struct r_rmtcall_args {
+ u_int32_t rmt_prog;
+ u_int32_t rmt_vers;
+ u_int32_t rmt_proc;
+ int rmt_localvers; /* whether to send port # or uaddr */
+ char *rmt_uaddr;
+ struct encap_parms rmt_args;
+};
+
+extern int debugging;
+extern int doabort;
+extern int verboselog;
+extern int insecure;
+extern int oldstyle_local;
+extern rpcblist_ptr list_rbl; /* A list of version 3 & 4 rpcbind services */
+
+#ifdef PORTMAP
+extern struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
+extern char *udptrans; /* Name of UDP transport */
+extern char *tcptrans; /* Name of TCP transport */
+extern char *udp_uaddr; /* Universal UDP address */
+extern char *tcp_uaddr; /* Universal TCP address */
+#endif
+
+int add_bndlist __P((struct netconfig *, struct netbuf *));
+bool_t is_bound __P((char *, char *));
+char *mergeaddr __P((SVCXPRT *, char *, char *, char *));
+struct netconfig *rpcbind_get_conf __P((char *));
+
+void rpcbs_init __P((void));
+void rpcbs_procinfo __P((rpcvers_t, rpcproc_t));
+void rpcbs_set __P((rpcvers_t, bool_t));
+void rpcbs_unset __P((rpcvers_t, bool_t));
+void rpcbs_getaddr __P((rpcvers_t, rpcprog_t, rpcvers_t, char *, char *));
+void rpcbs_rmtcall __P((rpcvers_t, rpcproc_t, rpcprog_t, rpcvers_t, rpcproc_t,
+ char *, rpcblist_ptr));
+void *rpcbproc_getstat __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+
+void rpcb_service_3 __P((struct svc_req *, SVCXPRT *));
+void rpcb_service_4 __P((struct svc_req *, SVCXPRT *));
+
+/* Common functions shared between versions */
+void *rpcbproc_set_com __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+void *rpcbproc_unset_com __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t));
+bool_t map_set __P((RPCB *, char *));
+bool_t map_unset __P((RPCB *, char *));
+void delete_prog __P((int));
+void *rpcbproc_getaddr_com __P((RPCB *, struct svc_req *, SVCXPRT *, rpcvers_t,
+ rpcvers_t));
+void *rpcbproc_gettime_com __P((void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t));
+void *rpcbproc_uaddr2taddr_com __P((void *, struct svc_req *,
+ SVCXPRT *, rpcvers_t));
+void *rpcbproc_taddr2uaddr_com __P((void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t));
+int create_rmtcall_fd __P((struct netconfig *));
+void rpcbproc_callit_com __P((struct svc_req *, SVCXPRT *, rpcvers_t,
+ rpcvers_t));
+void my_svc_run __P((void));
+
+void rpcbind_abort __P((void));
+void reap __P((int));
+void toggle_verboselog __P((int));
+
+int check_access __P((SVCXPRT *, rpcproc_t, void *, int));
+int check_callit __P((SVCXPRT *, struct r_rmtcall_args *, int));
+void logit __P((int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *));
+int is_loopback __P((struct netbuf *));
+
+#ifdef PORTMAP
+extern void pmap_service __P((struct svc_req *, SVCXPRT *));
+#endif
+
+void write_warmstart __P((void));
+void read_warmstart __P((void));
+
+char *addrmerge __P((struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
+ char *netid));
+void network_init __P((void));
+struct sockaddr *local_sa __P((int));
+
+/* For different getaddr semantics */
+#define RPCB_ALLVERS 0
+#define RPCB_ONEVERS 1
+
+#endif /* rpcbind_h */
diff --git a/usr.sbin/rpcbind/security.c b/usr.sbin/rpcbind/security.c
new file mode 100644
index 000000000000..8d784d6c6686
--- /dev/null
+++ b/usr.sbin/rpcbind/security.c
@@ -0,0 +1,283 @@
+/* $NetBSD: security.c,v 1.5 2000/06/08 09:01:05 fvdl Exp $ */
+/* $FreeBSD$ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/pmap_prot.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <syslog.h>
+#include <netdb.h>
+
+/*
+ * XXX for special case checks in check_callit.
+ */
+#include <rpcsvc/mount.h>
+#include <rpcsvc/rquota.h>
+#include <rpcsvc/nfs_prot.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+
+#include "rpcbind.h"
+
+#ifdef LIBWRAP
+# include <tcpd.h>
+#ifndef LIBWRAP_ALLOW_FACILITY
+# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
+#endif
+#ifndef LIBWRAP_ALLOW_SEVERITY
+# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
+#endif
+#ifndef LIBWRAP_DENY_FACILITY
+# define LIBWRAP_DENY_FACILITY LOG_AUTH
+#endif
+#ifndef LIBWRAP_DENY_SEVERITY
+# define LIBWRAP_DENY_SEVERITY LOG_WARNING
+#endif
+int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
+int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
+#endif
+
+#ifndef PORTMAP_LOG_FACILITY
+# define PORTMAP_LOG_FACILITY LOG_AUTH
+#endif
+#ifndef PORTMAP_LOG_SEVERITY
+# define PORTMAP_LOG_SEVERITY LOG_INFO
+#endif
+int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
+
+extern int verboselog;
+
+int
+check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, int rpcbvers)
+{
+ struct netbuf *caller = svc_getrpccaller(xprt);
+ struct sockaddr *addr = (struct sockaddr *)caller->buf;
+#ifdef LIBWRAP
+ struct request_info req;
+#endif
+ rpcprog_t prog = 0;
+ rpcb *rpcbp;
+ struct pmap *pmap;
+
+ /*
+ * The older PMAP_* equivalents have the same numbers, so
+ * they are accounted for here as well.
+ */
+ switch (proc) {
+ case RPCBPROC_GETADDR:
+ case RPCBPROC_SET:
+ case RPCBPROC_UNSET:
+ if (rpcbvers > PMAPVERS) {
+ rpcbp = (rpcb *)args;
+ prog = rpcbp->r_prog;
+ } else {
+ pmap = (struct pmap *)args;
+ prog = pmap->pm_prog;
+ }
+ if (proc == RPCBPROC_GETADDR)
+ break;
+ if (!insecure && !is_loopback(caller)) {
+ if (verboselog)
+ logit(log_severity, addr, proc, prog,
+ " declined (non-loopback sender)");
+ return 0;
+ }
+ break;
+ case RPCBPROC_CALLIT:
+ case RPCBPROC_INDIRECT:
+ case RPCBPROC_DUMP:
+ case RPCBPROC_GETTIME:
+ case RPCBPROC_UADDR2TADDR:
+ case RPCBPROC_TADDR2UADDR:
+ case RPCBPROC_GETVERSADDR:
+ case RPCBPROC_GETADDRLIST:
+ case RPCBPROC_GETSTAT:
+ default:
+ }
+
+#ifdef LIBWRAP
+ if (addr->sa_family == AF_LOCAL)
+ return 1;
+ request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
+ sock_methods(&req);
+ if(!hosts_access(&req)) {
+ logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
+ return 0;
+ }
+#endif
+ if (verboselog)
+ logit(log_severity, addr, proc, prog, "");
+ return 1;
+}
+
+int
+is_loopback(struct netbuf *nbuf)
+{
+ struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ if (!oldstyle_local)
+ return 0;
+ sin = (struct sockaddr_in *)addr;
+ return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
+ (ntohs(sin->sin_port) < IPPORT_RESERVED));
+#ifdef INET6
+ case AF_INET6:
+ if (!oldstyle_local)
+ return 0;
+ sin6 = (struct sockaddr_in6 *)addr;
+ return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
+ (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
+#endif
+ case AF_LOCAL:
+ return 1;
+ default:
+ }
+
+ return 0;
+}
+
+
+/* logit - report events of interest via the syslog daemon */
+void
+logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
+ const char *text)
+{
+ const char *procname;
+ char procbuf[32];
+ char *progname;
+ char progbuf[32];
+ char fromname[NI_MAXHOST];
+ struct rpcent *rpc;
+ static const char *procmap[] = {
+ /* RPCBPROC_NULL */ "null",
+ /* RPCBPROC_SET */ "set",
+ /* RPCBPROC_UNSET */ "unset",
+ /* RPCBPROC_GETADDR */ "getport/addr",
+ /* RPCBPROC_DUMP */ "dump",
+ /* RPCBPROC_CALLIT */ "callit",
+ /* RPCBPROC_GETTIME */ "gettime",
+ /* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
+ /* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
+ /* RPCBPROC_GETVERSADDR */ "getversaddr",
+ /* RPCBPROC_INDIRECT */ "indirect",
+ /* RPCBPROC_GETADDRLIST */ "getaddrlist",
+ /* RPCBPROC_GETSTAT */ "getstat"
+ };
+
+ /*
+ * Fork off a process or the portmap daemon might hang while
+ * getrpcbynumber() or syslog() does its thing.
+ */
+
+ if (fork() == 0) {
+ setproctitle("logit");
+
+ /* Try to map program number to name. */
+
+ if (prognum == 0) {
+ progname = "";
+ } else if ((rpc = getrpcbynumber((int) prognum))) {
+ progname = rpc->r_name;
+ } else {
+ snprintf(progname = progbuf, sizeof(progbuf), "%u",
+ (unsigned)prognum);
+ }
+
+ /* Try to map procedure number to name. */
+
+ if (procnum > (sizeof procmap / sizeof (char *))) {
+ snprintf(procbuf, sizeof procbuf, "%u",
+ (unsigned)procnum);
+ procname = procbuf;
+ } else
+ procname = procmap[procnum];
+
+ /* Write syslog record. */
+
+ if (addr->sa_family == AF_LOCAL)
+ strcpy(fromname, "unix");
+ else
+ getnameinfo(addr, addr->sa_len, fromname,
+ sizeof fromname, NULL, 0, NI_NUMERICHOST);
+
+ syslog(severity, "connect from %s to %s(%s)%s",
+ fromname, procname, progname, text);
+ _exit(0);
+ }
+}
+
+int
+check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum)
+{
+ struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
+
+ /*
+ * Always allow calling NULLPROC
+ */
+ if (args->rmt_proc == 0)
+ return 1;
+
+ /*
+ * XXX - this special casing sucks.
+ */
+ switch (args->rmt_prog) {
+ case RPCBPROG:
+ /*
+ * Allow indirect calls to ourselves in insecure mode.
+ * The is_loopback checks aren't useful then anyway.
+ */
+ if (!insecure)
+ goto deny;
+ break;
+ case MOUNTPROG:
+ if (args->rmt_proc != MOUNTPROC_MNT &&
+ args->rmt_proc != MOUNTPROC_UMNT)
+ break;
+ goto deny;
+ case YPBINDPROG:
+ if (args->rmt_proc != YPBINDPROC_SETDOM)
+ break;
+ /* FALLTHROUGH */
+ case YPPASSWDPROG:
+ case NFS_PROGRAM:
+ case RQUOTAPROG:
+ goto deny;
+ case YPPROG:
+ switch (args->rmt_proc) {
+ case YPPROC_ALL:
+ case YPPROC_MATCH:
+ case YPPROC_FIRST:
+ case YPPROC_NEXT:
+ goto deny;
+ default:
+ }
+ default:
+ }
+
+ return 1;
+deny:
+#ifdef LIBWRAP
+ logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
+ ": indirect call not allowed");
+#else
+ logit(0, sa, args->rmt_proc, args->rmt_prog,
+ ": indirect call not allowed");
+#endif
+ return 0;
+}
diff --git a/usr.sbin/rpcbind/util.c b/usr.sbin/rpcbind/util.c
new file mode 100644
index 000000000000..bf2001945e43
--- /dev/null
+++ b/usr.sbin/rpcbind/util.c
@@ -0,0 +1,381 @@
+/*
+ * $NetBSD: util.c,v 1.4 2000/08/03 00:04:30 fvdl Exp $
+ * $FreeBSD$
+ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden.
+ *
+ * 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 the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <sys/poll.h>
+#include <rpc/rpc.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netconfig.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#include "rpcbind.h"
+
+static struct sockaddr_in *local_in4;
+#ifdef INET6
+static struct sockaddr_in6 *local_in6;
+#endif
+
+static int bitmaskcmp __P((void *, void *, void *, int));
+#ifdef INET6
+static void in6_fillscopeid __P((struct sockaddr_in6 *));
+#endif
+
+/*
+ * For all bits set in "mask", compare the corresponding bits in
+ * "dst" and "src", and see if they match.
+ */
+static int
+bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
+{
+ int i, j;
+ u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
+ u_int8_t bitmask;
+
+ for (i = 0; i < bytelen; i++) {
+ for (j = 0; j < 8; j++) {
+ bitmask = 1 << j;
+ if (!(netmask[i] & bitmask))
+ continue;
+ if ((p1[i] & bitmask) != (p2[i] & bitmask))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Taken from ifconfig.c
+ */
+#ifdef INET6
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+}
+#endif
+
+char *
+addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
+ char *netid)
+{
+ struct ifaddrs *ifap, *ifp, *bestif;
+#ifdef INET6
+ struct sockaddr_in6 *servsin6, *sin6mask, *clntsin6, *ifsin6, *realsin6;
+ struct sockaddr_in6 *newsin6;
+#endif
+ struct sockaddr_in *servsin, *sinmask, *clntsin, *newsin, *ifsin;
+ struct netbuf *serv_nbp, *clnt_nbp = NULL, tbuf;
+ struct sockaddr *serv_sa;
+ struct sockaddr *clnt_sa;
+ struct sockaddr_storage ss;
+ struct netconfig *nconf;
+ struct sockaddr *clnt = caller->buf;
+ char *ret = NULL;
+
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr,
+ clnt_uaddr, netid);
+#endif
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL)
+ return NULL;
+
+ /*
+ * Local merge, just return a duplicate.
+ */
+ if (clnt_uaddr != NULL && strncmp(clnt_uaddr, "0.0.0.0.", 8) == 0)
+ return strdup(clnt_uaddr);
+
+ serv_nbp = uaddr2taddr(nconf, serv_uaddr);
+ if (serv_nbp == NULL)
+ return NULL;
+
+ serv_sa = (struct sockaddr *)serv_nbp->buf;
+ if (clnt_uaddr != NULL) {
+ clnt_nbp = uaddr2taddr(nconf, clnt_uaddr);
+ clnt_sa = (struct sockaddr *)clnt_nbp->buf;
+ } else {
+ clnt_sa = (struct sockaddr *)
+ malloc(sizeof (struct sockaddr_storage));
+ memcpy(clnt_sa, clnt, clnt->sa_len);
+ }
+
+ if (getifaddrs(&ifp) < 0)
+ return 0;
+
+ /*
+ * Loop through all interfaces. For each interface, see if the
+ * network portion of its address is equal to that of the client.
+ * If so, we have found the interface that we want to use.
+ */
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ if (ifap->ifa_addr->sa_family != clnt->sa_family ||
+ !(ifap->ifa_flags & IFF_UP))
+ continue;
+
+ switch (clnt->sa_family) {
+ case AF_INET:
+ /*
+ * realsin: address that recvfrom gave us.
+ * ifsin: address of interface being examined.
+ * clntsin: address that client want us to contact
+ * it on
+ * servsin: local address of RPC service.
+ * sinmask: netmask of this interface
+ * newsin: initially a copy of clntsin, eventually
+ * the merged address
+ */
+ servsin = (struct sockaddr_in *)serv_sa;
+ clntsin = (struct sockaddr_in *)clnt_sa;
+ sinmask = (struct sockaddr_in *)ifap->ifa_netmask;
+ newsin = (struct sockaddr_in *)&ss;
+ ifsin = (struct sockaddr_in *)ifap->ifa_addr;
+ if (!bitmaskcmp(&ifsin->sin_addr, &clntsin->sin_addr,
+ &sinmask->sin_addr, sizeof (struct in_addr))) {
+ /*
+ * Found it.
+ */
+ memcpy(newsin, ifap->ifa_addr,
+ clnt_sa->sa_len);
+ newsin->sin_port = servsin->sin_port;
+ tbuf.len = clnt_sa->sa_len;
+ tbuf.maxlen = sizeof (struct sockaddr_storage);
+ tbuf.buf = newsin;
+ goto found;
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ /*
+ * realsin6: address that recvfrom gave us.
+ * ifsin6: address of interface being examined.
+ * clntsin6: address that client want us to contact
+ * it on
+ * servsin6: local address of RPC service.
+ * sin6mask: netmask of this interface
+ * newsin6: initially a copy of clntsin, eventually
+ * the merged address
+ *
+ * For v6 link local addresses, if the client contacted
+ * us via a link-local address, and wants us to reply
+ * to one, use the scope id to see which one.
+ */
+ realsin6 = (struct sockaddr_in6 *)clnt;
+ ifsin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
+ in6_fillscopeid(ifsin6);
+ clntsin6 = (struct sockaddr_in6 *)clnt_sa;
+ servsin6 = (struct sockaddr_in6 *)serv_sa;
+ sin6mask = (struct sockaddr_in6 *)ifap->ifa_netmask;
+ newsin6 = (struct sockaddr_in6 *)&ss;
+ if (IN6_IS_ADDR_LINKLOCAL(&ifsin6->sin6_addr) &&
+ IN6_IS_ADDR_LINKLOCAL(&realsin6->sin6_addr) &&
+ IN6_IS_ADDR_LINKLOCAL(&clntsin6->sin6_addr)) {
+ if (ifsin6->sin6_scope_id !=
+ realsin6->sin6_scope_id)
+ continue;
+match:
+ memcpy(newsin6, ifsin6, clnt_sa->sa_len);
+ newsin6->sin6_port = servsin6->sin6_port;
+ tbuf.maxlen = sizeof (struct sockaddr_storage);
+ tbuf.len = clnt_sa->sa_len;
+ tbuf.buf = newsin6;
+ goto found;
+ }
+ if (!bitmaskcmp(&ifsin6->sin6_addr,
+ &clntsin6->sin6_addr, &sin6mask->sin6_addr,
+ sizeof (struct in6_addr)))
+ goto match;
+ break;
+#endif
+ default:
+ goto freeit;
+ }
+ }
+ /*
+ * Didn't find anything. Get the first possibly useful interface,
+ * preferring "normal" interfaces to point-to-point and loopback
+ * ones.
+ */
+ bestif = NULL;
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ if (ifap->ifa_addr->sa_family != clnt->sa_family ||
+ !(ifap->ifa_flags & IFF_UP))
+ continue;
+ if (!(ifap->ifa_flags & IFF_LOOPBACK) &&
+ !(ifap->ifa_flags & IFF_POINTOPOINT)) {
+ bestif = ifap;
+ break;
+ }
+ if (bestif == NULL)
+ bestif = ifap;
+ else if ((bestif->ifa_flags & IFF_LOOPBACK) &&
+ !(ifap->ifa_flags & IFF_LOOPBACK))
+ bestif = ifap;
+ }
+ ifap = bestif;
+found:
+ if (ifap != NULL)
+ ret = taddr2uaddr(nconf, &tbuf);
+freeit:
+ freenetconfigent(nconf);
+ free(serv_sa);
+ free(serv_nbp);
+ if (clnt_sa != NULL)
+ free(clnt_sa);
+ if (clnt_nbp != NULL)
+ free(clnt_nbp);
+ freeifaddrs(ifp);
+
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "addrmerge: returning %s\n", ret);
+#endif
+ return ret;
+}
+
+void
+network_init()
+{
+#ifdef INET6
+ struct ifaddrs *ifap, *ifp;
+ struct ipv6_mreq mreq6;
+ int ifindex, s;
+#endif
+ int ecode;
+ struct addrinfo hints, *res;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET;
+ if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
+ if (debugging)
+ fprintf(stderr, "can't get local ip4 address: %s\n",
+ gai_strerror(ecode));
+ } else {
+ local_in4 = (struct sockaddr_in *)malloc(sizeof *local_in4);
+ if (local_in4 == NULL) {
+ if (debugging)
+ fprintf(stderr, "can't alloc local ip4 addr\n");
+ }
+ memcpy(local_in4, res->ai_addr, sizeof *local_in4);
+ }
+
+#ifdef INET6
+ hints.ai_family = AF_INET6;
+ if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
+ if (debugging)
+ fprintf(stderr, "can't get local ip6 address: %s\n",
+ gai_strerror(ecode));
+ } else {
+ local_in6 = (struct sockaddr_in6 *)malloc(sizeof *local_in6);
+ if (local_in6 == NULL) {
+ if (debugging)
+ fprintf(stderr, "can't alloc local ip6 addr\n");
+ }
+ memcpy(local_in6, res->ai_addr, sizeof *local_in6);
+ }
+
+ /*
+ * Now join the RPC ipv6 multicast group on all interfaces.
+ */
+ if (getifaddrs(&ifp) < 0)
+ return;
+
+ mreq6.ipv6mr_interface = 0;
+ inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, &mreq6.ipv6mr_multiaddr);
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+
+ /*
+ * Loop through all interfaces. For each interface, see if the
+ * network portion of its address is equal to that of the client.
+ * If so, we have found the interface that we want to use.
+ */
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ if (ifap->ifa_addr->sa_family != AF_INET6 ||
+ !(ifap->ifa_flags & IFF_MULTICAST))
+ continue;
+ ifindex = if_nametoindex(ifap->ifa_name);
+ if (ifindex == mreq6.ipv6mr_interface)
+ /*
+ * Already did this one.
+ */
+ continue;
+ mreq6.ipv6mr_interface = ifindex;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
+ sizeof mreq6) < 0)
+ if (debugging)
+ perror("setsockopt v6 multicast");
+ }
+#endif
+
+ /* close(s); */
+}
+
+struct sockaddr *
+local_sa(int af)
+{
+ switch (af) {
+ case AF_INET:
+ return (struct sockaddr *)local_in4;
+#ifdef INET6
+ case AF_INET6:
+ return (struct sockaddr *)local_in6;
+#endif
+ default:
+ return NULL;
+ }
+}
diff --git a/usr.sbin/rpcbind/warmstart.c b/usr.sbin/rpcbind/warmstart.c
new file mode 100644
index 000000000000..fea278952f26
--- /dev/null
+++ b/usr.sbin/rpcbind/warmstart.c
@@ -0,0 +1,179 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * warmstart.c
+ * Allows for gathering of registrations from a earlier dumped file.
+ *
+ * Copyright (c) 1990 by Sun Microsystems, Inc.
+ */
+
+/*
+ * #ident "@(#)warmstart.c 1.7 93/07/05 SMI"
+ * $FreeBSD$/
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/xdr.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#include <rpc/pmap_prot.h>
+#endif
+#include <syslog.h>
+#include <unistd.h>
+
+#include "rpcbind.h"
+
+/*
+ * XXX this code is unsafe and is not used. It should be made safe.
+ */
+
+
+/* These files keep the pmap_list and rpcb_list in XDR format */
+#define RPCBFILE "/tmp/rpcbind.file"
+#ifdef PORTMAP
+#define PMAPFILE "/tmp/portmap.file"
+#endif
+
+static bool_t write_struct __P((char *, xdrproc_t, void *));
+static bool_t read_struct __P((char *, xdrproc_t, void *));
+
+static bool_t
+write_struct(char *filename, xdrproc_t structproc, void *list)
+{
+ FILE *fp;
+ XDR xdrs;
+ mode_t omask;
+
+ omask = umask(077);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ int i;
+
+ for (i = 0; i < 10; i++)
+ close(i);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ syslog(LOG_ERR,
+ "cannot open file = %s for writing", filename);
+ syslog(LOG_ERR, "cannot save any registration");
+ return (FALSE);
+ }
+ }
+ (void) umask(omask);
+ xdrstdio_create(&xdrs, fp, XDR_ENCODE);
+
+ if (structproc(&xdrs, list) == FALSE) {
+ syslog(LOG_ERR, "rpcbind: xdr_%s: failed", filename);
+ fclose(fp);
+ return (FALSE);
+ }
+ XDR_DESTROY(&xdrs);
+ fclose(fp);
+ return (TRUE);
+}
+
+static bool_t
+read_struct(char *filename, xdrproc_t structproc, void *list)
+{
+ FILE *fp;
+ XDR xdrs;
+ struct stat sbuf;
+
+ if (stat(filename, &sbuf) != 0) {
+ fprintf(stderr,
+ "rpcbind: cannot stat file = %s for reading\n", filename);
+ goto error;
+ }
+ if ((sbuf.st_uid != 0) || (sbuf.st_mode & S_IRWXG) ||
+ (sbuf.st_mode & S_IRWXO)) {
+ fprintf(stderr,
+ "rpcbind: invalid permissions on file = %s for reading\n",
+ filename);
+ goto error;
+ }
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ fprintf(stderr,
+ "rpcbind: cannot open file = %s for reading\n", filename);
+ goto error;
+ }
+ xdrstdio_create(&xdrs, fp, XDR_DECODE);
+
+ if (structproc(&xdrs, list) == FALSE) {
+ fprintf(stderr, "rpcbind: xdr_%s: failed\n", filename);
+ fclose(fp);
+ goto error;
+ }
+ XDR_DESTROY(&xdrs);
+ fclose(fp);
+ return (TRUE);
+
+error: fprintf(stderr, "rpcbind: will start from scratch\n");
+ return (FALSE);
+}
+
+void
+write_warmstart()
+{
+ (void) write_struct(RPCBFILE, xdr_rpcblist_ptr, &list_rbl);
+#ifdef PORTMAP
+ (void) write_struct(PMAPFILE, xdr_pmaplist_ptr, &list_pml);
+#endif
+
+}
+
+void
+read_warmstart()
+{
+ rpcblist_ptr tmp_rpcbl = NULL;
+#ifdef PORTMAP
+ struct pmaplist *tmp_pmapl = NULL;
+#endif
+ int ok1, ok2 = TRUE;
+
+ ok1 = read_struct(RPCBFILE, xdr_rpcblist_ptr, &tmp_rpcbl);
+ if (ok1 == FALSE)
+ return;
+#ifdef PORTMAP
+ ok2 = read_struct(PMAPFILE, xdr_pmaplist_ptr, &tmp_pmapl);
+#endif
+ if (ok2 == FALSE) {
+ xdr_free((xdrproc_t) xdr_rpcblist_ptr, (char *)&tmp_rpcbl);
+ return;
+ }
+ xdr_free((xdrproc_t) xdr_rpcblist_ptr, (char *)&list_rbl);
+ list_rbl = tmp_rpcbl;
+#ifdef PORTMAP
+ xdr_free((xdrproc_t) xdr_pmaplist_ptr, (char *)&list_pml);
+ list_pml = tmp_pmapl;
+#endif
+}
diff --git a/usr.sbin/ypbind/yp_ping.c b/usr.sbin/ypbind/yp_ping.c
index 558843f0c7fc..744eda07d795 100644
--- a/usr.sbin/ypbind/yp_ping.c
+++ b/usr.sbin/ypbind/yp_ping.c
@@ -310,7 +310,7 @@ get_reply:
} /* end successful completion */
else {
/* maybe our credentials need to be refreshed ... */
- if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
+ if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
nrefreshes--;
goto call_again;
}
@@ -502,7 +502,7 @@ int __yp_ping(restricted_addrs, cnt, dom, port)
clnt->cl_auth = authunix_create_default();
cu = (struct cu_data *)clnt->cl_private;
tv.tv_sec = 0;
- clnt_control(clnt, CLSET_TIMEOUT, &tv);
+ clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv);
ioctl(sock, FIONBIO, &dontblock);
oldfunc = clnt->cl_ops->cl_call;
clnt->cl_ops->cl_call = clntudp_a_call;
diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c
index d6e5e2be1c3a..5304422116c9 100644
--- a/usr.sbin/ypbind/ypbind.c
+++ b/usr.sbin/ypbind/ypbind.c
@@ -743,7 +743,7 @@ struct _dom_binding *ypdb;
ptr = (char *)&ypdb->dom_domain;
stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK,
xdr_domainname, (char *)&ptr, xdr_bool, (char *)&out,
- broadcast_result);
+ (resultproc_t)broadcast_result);
}
if (stat != RPC_SUCCESS) {
diff --git a/usr.sbin/yppush/yppush_main.c b/usr.sbin/yppush/yppush_main.c
index 39b5bdf43d76..ba25dda2a8db 100644
--- a/usr.sbin/yppush/yppush_main.c
+++ b/usr.sbin/yppush/yppush_main.c
@@ -415,7 +415,7 @@ int yp_push(server, map, tid)
job->stat = 0;
job->tid = tid;
job->port = xprt->xp_port;
- job->sock = xprt->xp_sock; /*XXX: Evil!! EEEEEEEVIL!!! */
+ job->sock = xprt->xp_fd; /*XXX: Evil!! EEEEEEEVIL!!! */
job->server = strdup(server);
job->map = strdup(map);
job->prognum = prognum;
@@ -437,8 +437,8 @@ int yp_push(server, map, tid)
* 2) Even in this day and age, there are still some *NIXes
* that don't support async socket I/O.
*/
- if (fcntl(xprt->xp_sock, F_SETOWN, getpid()) == -1 ||
- fcntl(xprt->xp_sock, F_SETFL, O_ASYNC) == -1) {
+ if (fcntl(xprt->xp_fd, F_SETOWN, getpid()) == -1 ||
+ fcntl(xprt->xp_fd, F_SETFL, O_ASYNC) == -1) {
yp_error("failed to set async I/O mode: %s",
strerror(errno));
yppush_exit(1);
diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c
index 5aa03e79c6b3..fdbac25c272a 100644
--- a/usr.sbin/ypserv/yp_dnslookup.c
+++ b/usr.sbin/ypserv/yp_dnslookup.c
@@ -434,7 +434,7 @@ ypstat yp_async_lookup_name(rqstp, name)
/* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */
type = -1; len = sizeof(type);
- if (getsockopt(rqstp->rq_xprt->xp_sock, SOL_SOCKET,
+ if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET,
SO_TYPE, &type, &len) == -1) {
yp_error("getsockopt failed: %s", strerror(errno));
return(YP_YPERR);
@@ -490,7 +490,7 @@ ypstat yp_async_lookup_addr(rqstp, addr)
/* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */
type = -1; len = sizeof(type);
- if (getsockopt(rqstp->rq_xprt->xp_sock, SOL_SOCKET,
+ if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET,
SO_TYPE, &type, &len) == -1) {
yp_error("getsockopt failed: %s", strerror(errno));
return(YP_YPERR);