From ce0e08e21d42c06c0014fae6b9d27144aa5109b0 Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Mon, 15 Dec 2008 17:04:23 -0500 Subject: [PATCH] Bring in a transport-independent RPC (TI-RPC). -rpcbind replaces portmap which is more secure. -Essentially this is the same thing FreeBSD did over 7 years ago (svn revision #74462). -This also updates utilities and the kernel build associated with this change. --- Makefile_upgrade.inc | 6 + etc/Makefile | 2 +- etc/defaults/rc.conf | 5 +- etc/netconfig | 20 + etc/rc.d/Makefile | 6 +- etc/rc.d/lockd | 44 + etc/rc.d/nfslocking | 36 - etc/rc.d/statd | 44 + etc/rpc | 6 +- include/Makefile | 3 +- include/netconfig.h | 97 + include/rpc/Makefile | 31 +- include/rpc/auth.h | 223 +- include/rpc/auth_des.h | 20 +- include/rpc/auth_kerb.h | 143 ++ include/rpc/clnt.h | 528 +++-- include/rpc/clnt_soc.h | 107 + include/rpc/clnt_stat.h | 84 + include/rpc/des_crypt.h | 50 +- include/rpc/{svc_auth.h => nettype.h} | 45 +- include/rpc/pmap_clnt.h | 14 +- include/rpc/pmap_prot.h | 14 +- include/rpc/pmap_rmt.h | 13 +- .../rpc/rpc_commondata.c => include/rpc/raw.h | 37 +- include/rpc/rpc.h | 58 +- include/rpc/rpc_com.h | 62 +- include/rpc/rpc_msg.h | 36 +- include/rpc/rpcb_clnt.h | 86 + include/rpc/rpcb_prot.x | 555 +++++ include/rpc/{rpc_com.h => rpcent.h} | 75 +- include/rpc/svc.h | 276 ++- include/rpc/svc_auth.h | 22 +- .../rpc/pmap_prot.c => include/rpc/svc_dg.h | 40 +- include/rpc/svc_soc.h | 116 + include/rpc/types.h | 59 +- include/rpc/xdr.h | 186 +- include/rpcsvc/bootparam_prot.x | 3 +- include/rpcsvc/nis.x | 4 +- include/rpcsvc/nislib.h | 4 +- include/rpcsvc/nlm_prot.x | 195 +- include/rpcsvc/pmap_prot.x | 9 +- include/rpcsvc/rstat.x | 9 +- include/rpcsvc/yp_prot.h | 32 +- include/rpcsvc/ypclnt.h | 4 +- lib/libc/gen/_pthread_stubs.c | 133 +- lib/libc/include/namespace.h | 2 +- lib/libc/include/reentrant.h | 136 ++ lib/libc/include/un-namespace.h | 2 +- lib/libc/rpc/LICENSE | 336 +++ lib/libc/rpc/Makefile.inc | 227 +- lib/libc/rpc/README | 361 ++- lib/libc/rpc/auth_des.c | 364 ++- lib/libc/rpc/auth_none.c | 96 +- lib/libc/rpc/auth_time.c | 54 +- lib/libc/rpc/auth_unix.c | 193 +- lib/libc/rpc/authdes_prot.c | 31 +- lib/libc/rpc/authunix_prot.c | 17 +- lib/libc/rpc/bindresvport.3 | 113 +- lib/libc/rpc/bindresvport.c | 48 +- lib/libc/rpc/clnt_bcast.c | 668 ++++++ lib/libc/rpc/clnt_dg.c | 768 +++++++ lib/libc/rpc/clnt_generic.c | 473 +++- lib/libc/rpc/clnt_perror.c | 155 +- lib/libc/rpc/clnt_raw.c | 161 +- lib/libc/rpc/clnt_simple.c | 187 +- lib/libc/rpc/clnt_tcp.c | 555 ----- lib/libc/rpc/clnt_udp.c | 573 ----- lib/libc/rpc/clnt_unix.c | 607 ----- lib/libc/rpc/clnt_vc.c | 809 +++++++ lib/libc/rpc/crypt_client.c | 32 +- lib/libc/rpc/get_myaddress.c | 115 - lib/libc/rpc/getnetconfig.3 | 223 ++ lib/libc/rpc/getnetconfig.c | 697 ++++++ lib/libc/rpc/getnetpath.3 | 171 ++ lib/libc/rpc/getnetpath.c | 270 +++ lib/libc/rpc/getpublickey.c | 12 +- lib/libc/rpc/getrpcent.3 | 37 +- lib/libc/rpc/getrpcent.c | 41 +- lib/libc/rpc/getrpcport.c | 23 +- lib/libc/rpc/key_call.c | 136 +- lib/libc/rpc/key_prot_xdr.c | 4 +- lib/libc/rpc/mt_misc.c | 117 + lib/libc/rpc/mt_misc.h | 67 + lib/libc/rpc/netconfig.5 | 132 ++ lib/libc/rpc/netname.c | 12 +- lib/libc/rpc/netnamer.c | 16 +- lib/libc/rpc/pmap_clnt.c | 113 +- lib/libc/rpc/pmap_getmaps.c | 39 +- lib/libc/rpc/pmap_getport.c | 47 +- lib/libc/rpc/pmap_prot.c | 10 +- lib/libc/rpc/pmap_prot2.c | 31 +- lib/libc/rpc/pmap_rmt.c | 321 +-- lib/libc/rpc/rpc.3 | 1999 ++++------------- lib/libc/rpc/rpc.5 | 51 +- lib/libc/rpc/rpc_callmsg.c | 62 +- lib/libc/rpc/rpc_clnt_auth.3 | 97 + lib/libc/rpc/rpc_clnt_calls.3 | 317 +++ lib/libc/rpc/rpc_clnt_create.3 | 515 +++++ {include => lib/libc}/rpc/rpc_com.h | 84 +- lib/libc/rpc/rpc_commondata.c | 7 +- lib/libc/rpc/rpc_dtablesize.c | 8 +- lib/libc/rpc/rpc_generic.c | 831 +++++++ lib/libc/rpc/rpc_prot.c | 123 +- lib/libc/rpc/rpc_secure.3 | 4 +- lib/libc/rpc/{rpc.3 => rpc_soc.3} | 309 ++- lib/libc/rpc/rpc_soc.c | 516 +++++ lib/libc/rpc/rpc_svc_calls.3 | 268 +++ lib/libc/rpc/rpc_svc_create.3 | 338 +++ lib/libc/rpc/rpc_svc_err.3 | 98 + lib/libc/rpc/rpc_svc_reg.3 | 184 ++ lib/libc/rpc/rpc_xdr.3 | 102 + lib/libc/rpc/rpcb_clnt.c | 1318 +++++++++++ lib/libc/rpc/rpcb_prot.c | 311 +++ lib/libc/rpc/rpcb_st_xdr.c | 260 +++ lib/libc/rpc/rpcbind.3 | 195 ++ lib/libc/rpc/rpcdname.c | 5 +- lib/libc/rpc/rtime.c | 19 +- lib/libc/rpc/svc.c | 513 +++-- lib/libc/rpc/svc_auth.c | 87 +- lib/libc/rpc/svc_auth_des.c | 9 +- lib/libc/rpc/svc_auth_unix.c | 39 +- lib/libc/rpc/svc_dg.c | 573 +++++ lib/libc/rpc/svc_generic.c | 304 +++ lib/libc/rpc/svc_raw.c | 192 +- lib/libc/rpc/svc_run.c | 63 +- lib/libc/rpc/svc_simple.c | 275 ++- lib/libc/rpc/svc_tcp.c | 458 ---- lib/libc/rpc/svc_udp.c | 459 ---- lib/libc/rpc/svc_unix.c | 499 ---- lib/libc/rpc/svc_vc.c | 750 +++++++ lib/libc/xdr/Makefile.inc | 13 +- lib/libc/xdr/xdr.3 | 136 +- lib/libc/xdr/xdr.c | 260 ++- lib/libc/xdr/xdr_array.c | 18 +- lib/libc/xdr/xdr_float.c | 77 +- lib/libc/xdr/xdr_mem.c | 96 +- lib/libc/xdr/xdr_rec.c | 383 +++- lib/libc/xdr/xdr_reference.c | 19 +- lib/libc/xdr/xdr_sizeof.c | 17 +- lib/libc/xdr/xdr_stdio.c | 47 +- lib/libc_rtld/Makefile | 1 + lib/librpcsvc/rnusers.c | 9 +- lib/librpcsvc/rstat.c | 11 +- lib/librpcsvc/rwall.c | 5 +- lib/librpcsvc/secretkey.c | 5 +- lib/librpcsvc/xcrypt.c | 43 +- lib/librpcsvc/yp_passwd.c | 13 +- lib/librpcsvc/yp_update.c | 23 +- sbin/mount_nfs/mount_nfs.c | 348 +-- sbin/mountd/Makefile | 2 +- sbin/mountd/mountd.c | 902 +++++--- sbin/nfsd/nfsd.8 | 65 +- sbin/nfsd/nfsd.c | 1002 +++++---- sbin/umount/Makefile | 2 +- sbin/umount/umount.c | 232 +- sys/conf/files | 4 +- sys/netproto/atm/spans/spans_kxdr.c | 3 +- .../netproto/atm/spans/spans_kxdr.h | 238 +- sys/netproto/atm/spans/spans_msg.c | 1 - sys/netproto/atm/spans/spans_xdr.x | 8 +- usr.bin/chpass/Makefile | 2 +- usr.bin/keylogin/keylogin.c | 3 +- usr.bin/passwd/Makefile | 2 +- usr.bin/rpcgen/rpc_clntout.c | 122 +- usr.bin/rpcgen/rpc_cout.c | 152 +- usr.bin/rpcgen/rpc_hout.c | 173 +- usr.bin/rpcgen/rpc_main.c | 340 +-- usr.bin/rpcgen/rpc_parse.c | 68 +- usr.bin/rpcgen/rpc_parse.h | 66 +- usr.bin/rpcgen/rpc_sample.c | 72 +- usr.bin/rpcgen/rpc_scan.c | 92 +- usr.bin/rpcgen/rpc_scan.h | 54 +- usr.bin/rpcgen/rpc_svcout.c | 416 ++-- usr.bin/rpcgen/rpc_tblout.c | 26 +- usr.bin/rpcgen/rpc_util.c | 111 +- usr.bin/rpcgen/rpc_util.h | 119 +- usr.bin/rpcgen/rpcgen.1 | 76 +- usr.bin/rpcinfo/Makefile | 6 +- usr.bin/rpcinfo/rpcinfo.8 | 403 +++- usr.bin/rpcinfo/rpcinfo.c | 1817 +++++++++++---- usr.bin/rup/rup.1 | 16 +- usr.bin/rup/rup.c | 42 +- usr.bin/rusers/Makefile | 1 - usr.bin/rusers/rusers.1 | 6 +- usr.bin/rusers/rusers.c | 43 +- usr.bin/rwall/rwall.1 | 12 +- usr.bin/rwall/rwall.c | 17 +- usr.bin/showmount/showmount.8 | 23 +- usr.bin/showmount/showmount.c | 74 +- usr.bin/ypwhich/ypwhich.1 | 12 +- usr.bin/ypwhich/ypwhich.c | 78 +- usr.sbin/Makefile | 2 +- usr.sbin/bootparamd/bootparamd/Makefile | 15 +- usr.sbin/bootparamd/bootparamd/README | 5 +- usr.sbin/bootparamd/bootparamd/bootparamd.8 | 2 +- usr.sbin/bootparamd/bootparamd/bootparamd.c | 27 +- usr.sbin/bootparamd/bootparamd/main.c | 8 +- usr.sbin/keyserv/Makefile | 2 +- usr.sbin/keyserv/keyserv.c | 153 +- usr.sbin/keyserv/keyserv.h | 3 +- usr.sbin/keyserv/keyserv_uid.c | 72 - usr.sbin/portmap/Makefile | 14 - usr.sbin/portmap/from_local.c | 225 -- usr.sbin/portmap/pmap_check.c | 251 --- usr.sbin/portmap/pmap_check.h | 42 - usr.sbin/portmap/pmap_dump/Makefile | 7 - usr.sbin/portmap/pmap_dump/pmap_dump.c | 65 - usr.sbin/portmap/pmap_set/Makefile | 7 - usr.sbin/portmap/pmap_set/pmap_set.c | 72 - usr.sbin/portmap/portmap.8 | 145 -- usr.sbin/portmap/portmap.c | 620 ----- usr.sbin/rpc.lockd/Makefile | 44 +- usr.sbin/rpc.lockd/lock_proc.c | 1227 ++++++++++ usr.sbin/rpc.lockd/lockd.c | 523 ++++- usr.sbin/rpc.lockd/lockd.h | 16 +- usr.sbin/rpc.lockd/lockd_lock.c | 743 ++++++ usr.sbin/rpc.lockd/lockd_lock.h | 23 + usr.sbin/rpc.lockd/procs.c | 865 ------- usr.sbin/rpc.lockd/rpc.lockd.8 | 112 +- usr.sbin/rpc.lockd/test.c | 114 +- usr.sbin/rpc.umntall/rpc.umntall.8 | 13 +- usr.sbin/rpc.umntall/rpc.umntall.c | 97 +- usr.sbin/rpc.yppasswdd/Makefile | 38 +- usr.sbin/rpc.yppasswdd/pw_copy.c | 147 -- usr.sbin/rpc.yppasswdd/pw_util.c | 177 -- usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8 | 13 +- usr.sbin/rpc.yppasswdd/yppasswdd_extern.h | 24 +- usr.sbin/rpc.yppasswdd/yppasswdd_main.c | 184 +- usr.sbin/rpc.yppasswdd/yppasswdd_server.c | 343 +-- usr.sbin/rpc.ypupdated/Makefile | 16 +- usr.sbin/rpc.ypupdated/update.c | 36 +- usr.sbin/rpc.ypupdated/yp_dbupdate.c | 3 +- usr.sbin/rpc.ypupdated/ypupdated_main.c | 3 +- usr.sbin/rpc.ypupdated/ypupdated_server.c | 3 +- usr.sbin/rpcbind/Makefile | 20 + usr.sbin/rpcbind/check_bound.c | 225 ++ usr.sbin/rpcbind/pmap_svc.c | 361 +++ usr.sbin/rpcbind/rpcb_stat.c | 206 ++ usr.sbin/rpcbind/rpcb_svc.c | 233 ++ usr.sbin/rpcbind/rpcb_svc_4.c | 454 ++++ usr.sbin/rpcbind/rpcb_svc_com.c | 1468 ++++++++++++ usr.sbin/rpcbind/rpcbind.8 | 149 ++ usr.sbin/rpcbind/rpcbind.c | 773 +++++++ usr.sbin/rpcbind/rpcbind.h | 142 ++ usr.sbin/rpcbind/security.c | 289 +++ usr.sbin/rpcbind/util.c | 382 ++++ usr.sbin/rpcbind/warmstart.c | 180 ++ usr.sbin/spray/spray.c | 9 +- usr.sbin/ypbind/yp_ping.c | 283 +-- usr.sbin/ypbind/ypbind.8 | 13 +- usr.sbin/ypbind/ypbind.c | 87 +- usr.sbin/yppush/Makefile | 15 +- usr.sbin/yppush/yppush.8 | 15 +- usr.sbin/yppush/yppush_main.c | 200 +- usr.sbin/ypserv/Makefile | 31 +- usr.sbin/ypserv/Makefile.yp | 182 +- usr.sbin/ypserv/yp_access.c | 64 +- usr.sbin/ypserv/yp_dblookup.c | 105 +- usr.sbin/ypserv/yp_dnslookup.c | 134 +- usr.sbin/ypserv/yp_error.c | 11 +- usr.sbin/ypserv/yp_extern.h | 6 +- usr.sbin/ypserv/yp_main.c | 63 +- usr.sbin/ypserv/yp_server.c | 53 +- usr.sbin/ypserv/yp_svc_udp.c | 23 +- usr.sbin/ypserv/ypinit.8 | 8 +- usr.sbin/ypserv/ypinit.sh | 18 +- usr.sbin/ypserv/ypserv.8 | 45 +- 267 files changed, 31669 insertions(+), 14892 deletions(-) create mode 100644 etc/netconfig create mode 100644 etc/rc.d/lockd delete mode 100644 etc/rc.d/nfslocking create mode 100644 etc/rc.d/statd create mode 100644 include/netconfig.h create mode 100644 include/rpc/auth_kerb.h create mode 100644 include/rpc/clnt_soc.h create mode 100644 include/rpc/clnt_stat.h copy include/rpc/{svc_auth.h => nettype.h} (63%) copy lib/libc/rpc/rpc_commondata.c => include/rpc/raw.h (70%) create mode 100644 include/rpc/rpcb_clnt.h create mode 100644 include/rpc/rpcb_prot.x copy include/rpc/{rpc_com.h => rpcent.h} (54%) copy lib/libc/rpc/pmap_prot.c => include/rpc/svc_dg.h (62%) create mode 100644 include/rpc/svc_soc.h create mode 100644 lib/libc/include/reentrant.h create mode 100644 lib/libc/rpc/LICENSE create mode 100644 lib/libc/rpc/clnt_bcast.c create mode 100644 lib/libc/rpc/clnt_dg.c delete mode 100644 lib/libc/rpc/clnt_tcp.c delete mode 100644 lib/libc/rpc/clnt_udp.c delete mode 100644 lib/libc/rpc/clnt_unix.c create mode 100644 lib/libc/rpc/clnt_vc.c delete mode 100644 lib/libc/rpc/get_myaddress.c create mode 100644 lib/libc/rpc/getnetconfig.3 create mode 100644 lib/libc/rpc/getnetconfig.c create mode 100644 lib/libc/rpc/getnetpath.3 create mode 100644 lib/libc/rpc/getnetpath.c create mode 100644 lib/libc/rpc/mt_misc.c create mode 100644 lib/libc/rpc/mt_misc.h create mode 100644 lib/libc/rpc/netconfig.5 create mode 100644 lib/libc/rpc/rpc_clnt_auth.3 create mode 100644 lib/libc/rpc/rpc_clnt_calls.3 create mode 100644 lib/libc/rpc/rpc_clnt_create.3 copy {include => lib/libc}/rpc/rpc_com.h (50%) create mode 100644 lib/libc/rpc/rpc_generic.c copy lib/libc/rpc/{rpc.3 => rpc_soc.3} (85%) create mode 100644 lib/libc/rpc/rpc_soc.c create mode 100644 lib/libc/rpc/rpc_svc_calls.3 create mode 100644 lib/libc/rpc/rpc_svc_create.3 create mode 100644 lib/libc/rpc/rpc_svc_err.3 create mode 100644 lib/libc/rpc/rpc_svc_reg.3 create mode 100644 lib/libc/rpc/rpc_xdr.3 create mode 100644 lib/libc/rpc/rpcb_clnt.c create mode 100644 lib/libc/rpc/rpcb_prot.c create mode 100644 lib/libc/rpc/rpcb_st_xdr.c create mode 100644 lib/libc/rpc/rpcbind.3 create mode 100644 lib/libc/rpc/svc_dg.c create mode 100644 lib/libc/rpc/svc_generic.c delete mode 100644 lib/libc/rpc/svc_tcp.c delete mode 100644 lib/libc/rpc/svc_udp.c delete mode 100644 lib/libc/rpc/svc_unix.c create mode 100644 lib/libc/rpc/svc_vc.c copy include/rpc/xdr.h => sys/netproto/atm/spans/spans_kxdr.h (57%) delete mode 100644 usr.sbin/keyserv/keyserv_uid.c delete mode 100644 usr.sbin/portmap/Makefile delete mode 100644 usr.sbin/portmap/from_local.c delete mode 100644 usr.sbin/portmap/pmap_check.c delete mode 100644 usr.sbin/portmap/pmap_check.h delete mode 100644 usr.sbin/portmap/pmap_dump/Makefile delete mode 100644 usr.sbin/portmap/pmap_dump/pmap_dump.c delete mode 100644 usr.sbin/portmap/pmap_set/Makefile delete mode 100644 usr.sbin/portmap/pmap_set/pmap_set.c delete mode 100644 usr.sbin/portmap/portmap.8 delete mode 100644 usr.sbin/portmap/portmap.c create mode 100644 usr.sbin/rpc.lockd/lock_proc.c create mode 100644 usr.sbin/rpc.lockd/lockd_lock.c create mode 100644 usr.sbin/rpc.lockd/lockd_lock.h delete mode 100644 usr.sbin/rpc.lockd/procs.c delete mode 100644 usr.sbin/rpc.yppasswdd/pw_copy.c delete mode 100644 usr.sbin/rpc.yppasswdd/pw_util.c create mode 100644 usr.sbin/rpcbind/Makefile create mode 100644 usr.sbin/rpcbind/check_bound.c create mode 100644 usr.sbin/rpcbind/pmap_svc.c create mode 100644 usr.sbin/rpcbind/rpcb_stat.c create mode 100644 usr.sbin/rpcbind/rpcb_svc.c create mode 100644 usr.sbin/rpcbind/rpcb_svc_4.c create mode 100644 usr.sbin/rpcbind/rpcb_svc_com.c create mode 100644 usr.sbin/rpcbind/rpcbind.8 create mode 100644 usr.sbin/rpcbind/rpcbind.c create mode 100644 usr.sbin/rpcbind/rpcbind.h create mode 100644 usr.sbin/rpcbind/security.c create mode 100644 usr.sbin/rpcbind/util.c create mode 100644 usr.sbin/rpcbind/warmstart.c diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 081fb5495d..e8f0d82b8e 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -996,3 +996,9 @@ TO_REMOVE+=/usr/share/examples/cvsup/DragonFly-release1_12-supfile TO_REMOVE+=/usr/share/examples/cvsup/DragonFly-release2_0-supfile TO_REMOVE+=/usr/share/examples/cvsup/DragonFly-src-supfile TO_REMOVE+=/usr/include/pcap-bpf.h +TO_REMOVE+=/etc/rc.d/nfslocking +TO_REMOVE+=/usr/sbin/pmap_dump +TO_REMOVE+=/usr/sbin/pmap_set +TO_REMOVE+=/usr/sbin/portmap +TO_REMOVE+=/usr/share/man/cat8/portmap.8.gz +TO_REMOVE+=/usr/share/man/man8/portmap.8.gz diff --git a/etc/Makefile b/etc/Makefile index e00523de3b..d0b07c2107 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -30,7 +30,7 @@ BIN1= amd.map auth.conf \ ftpusers group \ hosts hosts.allow host.conf hosts.equiv hosts.lpd \ inetd.conf login.access login.conf \ - motd modems networks newsyslog.conf \ + motd modems netconfig networks newsyslog.conf \ pf.conf phones printcap profile \ remote sensorsd.conf \ shells sysctl.conf syslog.conf usbd.conf \ diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 9e72ffeb1e..a7ad2aefe2 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -201,11 +201,12 @@ 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="" # bufspace (in packets) for client rpc_lockd_enable="NO" # Run NFS rpc.lockd needed for client/server. +rpc_lockd_flags="" # Flags to rpc.lockd (if enabled). rpc_statd_enable="NO" # Run NFS rpc.statd needed for client/server. +rpc_statd_flags="" # Flags to rpc.statd (if enabled). rpc_umntall_enable="YES" # Run NFS rpc.umntall on boot and shutdown rpcbind_enable="NO" # Run the portmapper service (YES/NO). -# this is rpcbind in 5.x -rpcbind_program="/usr/sbin/portmap" # path to rpcbind, if you want a different one. +rpcbind_program="/usr/sbin/rpcbind" # path to rpcbind, if you want a different one. rpcbind_flags="" # Flags to rpcbind (if enabled). rpc_ypupdated_enable="NO" # Run if NIS master and SecureRPC (or NO). keyserv_enable="NO" # Run the SecureRPC keyserver (or NO). diff --git a/etc/netconfig b/etc/netconfig new file mode 100644 index 0000000000..0f2fbcd6e1 --- /dev/null +++ b/etc/netconfig @@ -0,0 +1,20 @@ +# $FreeBSD: src/etc/netconfig,v 1.3 2002/12/16 22:24:25 mbr Exp $ +# $DragonFly$ +# +# 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: +# +# \ +# +# +# The and fields are always empty in DragonFly. +# +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 - - - diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 0ede6d0c9d..37100d75e3 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -14,15 +14,15 @@ FILES= DAEMON LOGIN NETWORKING SERVERS abi accounting addswap adjkerntz \ inetd initdiskless initrandom ip6fw ipfilter ipfs ipfw ipmon \ ipnat ipsec ipxrouted isdnd jail \ kadmind kerberos keyserv kpasswdd \ - ldconfig local localdaemons lpd \ + ldconfig local localdaemons lockd lpd \ mixer motd mountcritlocal mountcritremote \ mountd moused mroute6d mrouted msgs \ named netif netoptions newsyslog \ - network_ipv6 nfsclient nfsd nfslocking nfsserver nisdomain \ + network_ipv6 nfsclient nfsd nfsserver nisdomain \ dntpd othermta pf pflog ppp ppp-user pppoed pwcheck \ quota random rarpd rcconf.sh resident rndcontrol root route6d routed \ routing rpcbind rtadvd rtsold rwho sysdb savecore sdpd securelevel \ - sendmail sensorsd serial sppp sshd swap1 syscons sysctl syslogd \ + sendmail sensorsd serial sppp sshd statd swap1 syscons sysctl syslogd \ timed ttys usbd varsym vinum virecover watchdogd wpa_supplicant \ ypbind yppasswdd ypserv ypset ypupdated ypxfrd FILESDIR= /etc/rc.d diff --git a/etc/rc.d/lockd b/etc/rc.d/lockd new file mode 100644 index 0000000000..d660c7dcef --- /dev/null +++ b/etc/rc.d/lockd @@ -0,0 +1,44 @@ +#!/bin/sh +# +# FreeBSD History: src/etc/rc.d/nfslocking,v 1.11 2004/10/07 13:55:26 mtm +# $FreeBSD: src/etc/rc.d/lockd,v 1.22 2008/07/16 19:50:29 dougb Exp $ +# $DragonFly$ +# + +# PROVIDE: lockd +# REQUIRE: nfsserver nfsclient nfsd rpcbind statd +# BEFORE: DAEMON +# KEYWORD: nojail shutdown + +. /etc/rc.subr + +name="lockd" +rcvar=rpc_lockd_enable +command="/usr/sbin/rpc.${name}" +start_precmd='lockd_precmd' +stop_precmd='checkyesno nfs_server_enable || checkyesno nfs_client_enable' +status_precmd=$stop_precmd + +# Make sure that we are either an NFS client or server, and that we get +# the correct flags from rc.conf(5). +# +lockd_precmd() +{ + local ret + ret=0 + + if ! checkyesno nfs_server_enable && ! checkyesno nfs_client_enable + then + ret=1 + fi + if ! checkyesno rpcbind_enable && \ + ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 + then + force_depend rpcbind || ret=1 + fi + rc_flags=${rpc_lockd_flags} + return ${ret} +} + +load_rc_config $name +run_rc_command $1 diff --git a/etc/rc.d/nfslocking b/etc/rc.d/nfslocking deleted file mode 100644 index aa4425624a..0000000000 --- a/etc/rc.d/nfslocking +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# $NetBSD: nfslocking,v 1.6 2002/03/24 15:52:41 lukem Exp $ -# $FreeBSD: src/etc/rc.d/nfslocking,v 1.4 2003/01/20 18:57:16 mtm Exp $ -# $DragonFly: src/etc/rc.d/nfslocking,v 1.4 2005/11/19 21:47:32 swildner Exp $ -# - -# PROVIDE: nfslocking -# REQUIRE: nfsserver nfsclient nfsd -# BEFORE: DAEMON - -. /etc/rc.subr - -arg=$1 - -RCVAR_SERVER="nfs_server_enable" -RCVAR_CLIENT="nfs_client_enable" -RCVAR_STATD="rpc_statd_enable" -RCVAR_LOCKD="rpc_lockd_enable" - -start_precmd='checkyesno ${RCVAR_SERVER} || checkyesno ${RCVAR_CLIENT} || - [ -n "$rc_force" ]' -stop_precmd=$start_precmd -status_precmd=$start_precmd - -name="statd" -rcvar=${RCVAR_STATD} -command="/usr/sbin/rpc.${name}" -load_rc_config $name -run_rc_command "$arg" - -name="lockd" -rcvar=${RCVAR_LOCKD} -command="/usr/sbin/rpc.${name}" -load_rc_config $name -run_rc_command "$arg" diff --git a/etc/rc.d/statd b/etc/rc.d/statd new file mode 100644 index 0000000000..035a4352c2 --- /dev/null +++ b/etc/rc.d/statd @@ -0,0 +1,44 @@ +#!/bin/sh +# +# FreeBSD History: src/etc/rc.d/nfslocking,v 1.11 2004/10/07 13:55:26 mtm Exp +# $FreeBSD: src/etc/rc.d/statd,v 1.21 2008/07/16 19:50:29 dougb Exp $ +# $DragonFly$ +# + +# PROVIDE: statd +# REQUIRE: nfsserver nfsclient nfsd rpcbind +# BEFORE: DAEMON +# KEYWORD: nojail shutdown + +. /etc/rc.subr + +name="statd" +rcvar=rpc_statd_enable +command="/usr/sbin/rpc.${name}" +start_precmd='statd_precmd' +stop_precmd='checkyesno nfs_server_enable || checkyesno nfs_client_enable' +status_precmd=$stop_precmd + +# Make sure that we are either an NFS client or server, and that we get +# the correct flags from rc.conf(5). +# +statd_precmd() +{ + local ret + ret=0 + + if ! checkyesno nfs_server_enable && ! checkyesno nfs_client_enable + then + ret=1 + fi + if ! checkyesno rpcbind_enable && \ + ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 + then + force_depend rpcbind || ret=1 + fi + rc_flags=${rpc_statd_flags} + return ${ret} +} + +load_rc_config $name +run_rc_command $1 diff --git a/etc/rpc b/etc/rpc index dcd9973a50..d3efcbfef7 100644 --- a/etc/rpc +++ b/etc/rpc @@ -1,9 +1,9 @@ # -# $FreeBSD: src/etc/rpc,v 1.7.2.4 2002/04/15 00:44:13 dougb Exp $ +# $FreeBSD: src/etc/rpc,v 1.11 2004/06/06 11:46:27 schweikh Exp $ # $DragonFly: src/etc/rpc,v 1.2 2003/06/17 04:24:45 dillon Exp $ # rpc 88/08/01 4.0 RPCSRC; from 1.12 99/07/25 SMI # -portmapper 100000 portmap sunrpc rpcbind +rpcbind 100000 portmap sunrpc rpcbind rstatd 100001 rstat rstat_svc rup perfmeter rusersd 100002 rusers nfs 100003 nfsprog @@ -31,7 +31,7 @@ bootparamd 100026 bootparam ypupdated 100028 ypupdate keyserv 100029 keyserver sunlink_mapper 100033 -tfsd 100037 +tfsd 100037 nsed 100038 nsemntd 100039 showfhd 100043 showfh diff --git a/include/Makefile b/include/Makefile index 0d1c07c792..9dd7873fbf 100644 --- a/include/Makefile +++ b/include/Makefile @@ -15,7 +15,8 @@ INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \ fts.h ftw.h getopt.h glob.h grp.h histedit.h \ iconv.h ieeefp.h ifaddrs.h iso646.h inttypes.h \ langinfo.h libgen.h limits.h link.h locale.h malloc.h math.h memory.h \ - mpool.h monetary.h ndbm.h netdb.h nl_types.h nlist.h objformat.h \ + mpool.h monetary.h ndbm.h netconfig.h \ + netdb.h nl_types.h nlist.h objformat.h \ paths.h pthread.h pthread_np.h pwd.h \ ranlib.h readpassphrase.h regex.h regexp.h resolv.h re_comp.h rmd160.h \ search.h setjmp.h sgtty.h \ diff --git a/include/netconfig.h b/include/netconfig.h new file mode 100644 index 0000000000..b39b9b5c0b --- /dev/null +++ b/include/netconfig.h @@ -0,0 +1,97 @@ +/* $NetBSD: netconfig.h,v 1.1 2000/06/02 22:57:54 fvdl Exp $ */ +/* $FreeBSD: src/include/netconfig.h,v 1.3 2002/03/23 17:24:53 imp Exp $ */ +/* $DragonFly$ */ + + +#ifndef _NETCONFIG_H_ +#define _NETCONFIG_H_ + +#include + +#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(void); +struct netconfig *getnetconfig(void *); +struct netconfig *getnetconfigent(const char *); +void freenetconfigent(struct netconfig *); +int endnetconfig(void *); + +void *setnetpath(void); +struct netconfig *getnetpath(void *); +int endnetpath(void *); + +void nc_perror(const char *); +char *nc_sperror(void); +__END_DECLS + +#endif /* _NETCONFIG_H_ */ diff --git a/include/rpc/Makefile b/include/rpc/Makefile index 197b06f74b..cd3d39731e 100644 --- a/include/rpc/Makefile +++ b/include/rpc/Makefile @@ -1,10 +1,31 @@ -# $FreeBSD: src/include/rpc/Makefile,v 1.2.2.1 2002/07/22 14:21:46 ru Exp $ +# $FreeBSD: src/include/rpc/Makefile,v 1.2 2002/05/12 16:00:48 ru Exp $ # $DragonFly: src/include/rpc/Makefile,v 1.2 2003/06/17 04:25:58 dillon Exp $ -NOOBJ= noobj -INCS= 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 +.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} + +INCS= ${HFILES} ${XFILES} ${HDRS} INCSDIR=${INCLUDEDIR}/rpc +.x.h: + ${RPCCOM} -h -DWANT_NFS3 ${.IMPSRC} -o ${.TARGET} + .include diff --git a/include/rpc/auth.h b/include/rpc/auth.h index 4573e4951c..71ae812a2a 100644 --- a/include/rpc/auth.h +++ b/include/rpc/auth.h @@ -28,7 +28,9 @@ * * from: @(#)auth.h 1.17 88/02/08 SMI * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC - * $FreeBSD: src/include/rpc/auth.h,v 1.15 1999/08/27 23:45:02 peter Exp $ + * from: @(#)auth.h 1.43 98/02/02 SMI + * $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ + * $FreeBSD: src/include/rpc/auth.h,v 1.21 2006/02/28 16:02:26 deischen Exp $ * $DragonFly: src/include/rpc/auth.h,v 1.4 2004/02/26 13:58:26 joerg Exp $ */ @@ -38,18 +40,81 @@ * Copyright (C) 1984, Sun Microsystems, Inc. * * The data structures are completely opaque to the client. The client - * is required to pass a AUTH * to routines that create rpc + * is required to pass an AUTH * to routines that create rpc * "sessions". */ #ifndef _RPC_AUTH_H #define _RPC_AUTH_H +#include +#include #include #include #define MAX_AUTH_BYTES 400 #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 */ @@ -68,12 +133,23 @@ 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]; }; @@ -90,31 +166,28 @@ 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(XDR *, struct opaque_auth *); -__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) (struct __rpc_auth *); + void (*ah_nextverf) (struct __auth *); /* nextverf & serialize */ - int (*ah_marshal) (struct __rpc_auth *, XDR *); + int (*ah_marshal) (struct __auth *, XDR *); /* validate verifier */ - int (*ah_validate) (struct __rpc_auth *, + int (*ah_validate) (struct __auth *, struct opaque_auth *); /* refresh credentials */ - int (*ah_refresh) (struct __rpc_auth *); + int (*ah_refresh) (struct __auth *, void *); /* destroy this structure */ - void (*ah_destroy) (struct __rpc_auth *); + void (*ah_destroy) (struct __auth *); } *ah_ops; - caddr_t ah_private; + void *ah_private; } AUTH; @@ -141,10 +214,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)) @@ -152,14 +225,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; @@ -168,93 +243,113 @@ extern struct opaque_auth _null_auth; * int *aup_gids; */ __BEGIN_DECLS -struct sockaddr_in; AUTH *authunix_create(char *, int, int, int, int *); AUTH *authunix_create_default(void); AUTH *authnone_create(void); __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 AUTH *authdes_create(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. - */ -AUTH *authdes_pk_create(char *, netobj *, u_int, struct sockaddr *, - des_block *, nis_server *); -#endif +AUTH *authdes_seccreate(const char *, const u_int, const char *, + const des_block *); __END_DECLS +__BEGIN_DECLS +bool_t xdr_opaque_auth(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 -int netname2user(char *, uid_t *, gid_t *, int *, gid_t *); -int netname2host(char *, char *, int); int getnetname(char *); -int user2netname(char *, uid_t, char *); -int host2netname(char *, char *, char *); +int host2netname(char *, const char *, const char *); +int user2netname(char *, const uid_t, const char *); +int netname2user(char *, uid_t *, gid_t *, int *, gid_t *); +int netname2host(char *, char *, const int); 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 int key_decryptsession(const char *, des_block *); -int key_decryptsession_pk(char *, netobj *, des_block *); int key_encryptsession(const char *, des_block *); -int key_encryptsession_pk(char *, netobj *, des_block *); int key_gendes(des_block *); int key_setsecret(const char *); int key_secretkey_is_set(void); -int key_setnet(struct netstarg *); -int key_get_conv(char *, des_block *); __END_DECLS /* * Publickey routines. */ __BEGIN_DECLS -int getpublickey(char *, char *); -int getpublicandprivatekey(char *, char *); +int getpublickey(const char *, char *); +int getpublicandprivatekey(const char *, char *); int getsecretkey(char *, char *, char *); __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 +AUTH *authkerb_seccreate(const char *, const char *, const char *, + const u_int, const char *, int *); +__END_DECLS + +/* + * 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 +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 (struct svc_req *, struct rpc_msg *); +enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); +enum auth_stat _svcauth_unix (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 7aee4e81a5..7012aaf917 100644 --- a/include/rpc/auth_des.h +++ b/include/rpc/auth_des.h @@ -26,12 +26,14 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI + * from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC + * from: @(#)auth_des.h 1.14 94/04/25 SMI + * $FreeBSD: src/include/rpc/auth_des.h,v 1.3 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpc/auth_des.h,v 1.2 2003/11/14 01:01:50 dillon Exp $ */ /* - * Copyright (c) 1988 by Sun Microsystems, Inc. + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* @@ -104,8 +106,20 @@ 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 +int authdes_getucred(struct authdes_cred *, uid_t *, gid_t *, int *, gid_t *); +__END_DECLS + __BEGIN_DECLS -extern int authdes_getucred ( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * ); +bool_t xdr_authdes_cred(XDR *, struct authdes_cred *); +bool_t xdr_authdes_verf(XDR *, struct authdes_verf *); +int rtime(dev_t, struct netbuf *, int, struct timeval *, struct timeval *); +void kgetnetname(char *); +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 0000000000..7d775699c3 --- /dev/null +++ b/include/rpc/auth_kerb.h @@ -0,0 +1,143 @@ +/* + * 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 + * + * $FreeBSD: src/include/rpc/auth_kerb.h,v 1.3 2007/02/02 18:11:18 schweikh Exp $ + * $DragonFly$ + */ +/* + * 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 + +#include +#include +#include +#include +#include + +/* + * 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 ce5a0d7391..a823d1ed32 100644 --- a/include/rpc/clnt.h +++ b/include/rpc/clnt.h @@ -1,4 +1,21 @@ /* + * The contents of this file are subject to the Sun Standards + * License Version 1.0 the (the "License";) You may not use + * this file except in compliance with the License. You may + * obtain a copy of the License at lib/libc/rpc/LICENSE + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is Copyright 1998 by Sun Microsystems, Inc + * + * The Initial Developer of the Original Code is: Sun + * Microsystems, Inc. + * + * All Rights Reserved. + * * 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 @@ -26,66 +43,44 @@ * 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: src/include/rpc/clnt.h,v 1.11.2.1 2001/06/28 21:44:09 iedowse Exp $ + * $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl Exp $ + * $FreeBSD: src/include/rpc/clnt.h,v 1.21 2003/01/24 01:47:55 fjoe Exp $ * $DragonFly: src/include/rpc/clnt.h,v 1.6 2005/11/13 12:27:04 swildner Exp $ */ /* * clnt.h - Client side remote procedure call interface. * - * Copyright (C) 1984, Sun Microsystems, Inc. + * Copyright (c) 1986-1991,1994-1999 by Sun Microsystems, Inc. + * All rights reserved. */ #ifndef _RPC_CLNT_H_ #define _RPC_CLNT_H_ +#include #include +#include #include /* - * 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. @@ -96,8 +91,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; @@ -113,34 +108,58 @@ 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 { AUTH *cl_auth; /* authenticator */ struct clnt_ops { /* call remote procedure */ - enum clnt_stat (*cl_call) (struct __rpc_client *, - u_long, xdrproc_t, caddr_t, xdrproc_t, - caddr_t, struct timeval); + enum clnt_stat (*cl_call)(struct __rpc_client *, + rpcproc_t, xdrproc_t, void *, xdrproc_t, + void *, struct timeval); /* abort a call */ - void (*cl_abort) (struct __rpc_client *); + void (*cl_abort)(struct __rpc_client *); /* get specific error code */ - void (*cl_geterr) (struct __rpc_client *, + void (*cl_geterr)(struct __rpc_client *, struct rpc_err *); /* frees results */ - bool_t (*cl_freeres) (struct __rpc_client *, - xdrproc_t, caddr_t); + bool_t (*cl_freeres)(struct __rpc_client *, + xdrproc_t, void *); /* destroy this structure */ - void (*cl_destroy) (struct __rpc_client *); + void (*cl_destroy)(struct __rpc_client *); /* the ioctl() of rpc */ - bool_t (*cl_control) (struct __rpc_client *, u_int, - void *); + bool_t (*cl_control)(struct __rpc_client *, u_int, + void *); } *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 * @@ -152,19 +171,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; + * void *argsp; * xdrproc_t xres; - * caddr_t resp; + * void *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, \ + argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, \ + argsp, xres, resp, secs)) /* * void @@ -188,7 +207,7 @@ typedef struct __rpc_client { * CLNT_FREERES(rh, xres, resp); * CLIENT *rh; * xdrproc_t xres; - * caddr_t resp; + * void *resp; */ #define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) #define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) @@ -204,43 +223,32 @@ 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) */ +#define CLSET_ASYNC 19 #define CLSET_CONNECT 20 /* Use connect() for UDP. (int) */ -/* - * Operations which GSSAPI needs. (Bletch.) - */ -#define CLGET_LOCAL_ADDR 19 /* get local addr (sockaddr) */ - - /* * void * CLNT_DESTROY(rh); @@ -256,16 +264,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 @@ -274,108 +282,156 @@ typedef struct __rpc_client { */ /* - * Memory based rpc (for speed check and testing) - * CLIENT * - * clntraw_create(prog, vers) - * u_long prog; - * u_long vers; + * Generic client creation routine. Supported protocols are those that + * belong to the nettype namespace (/etc/netconfig). */ __BEGIN_DECLS -extern CLIENT *clntraw_create (u_long, u_long); -__END_DECLS +extern CLIENT *clnt_create(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. Just like clnt_create(), except + * it takes an additional timeout parameter. + */ +extern CLIENT * clnt_create_timed(const char *, const rpcprog_t, + const rpcvers_t, const char *, const struct timeval *); +/* + * + * const char *hostname; -- hostname + * const rpcprog_t prog; -- program number + * const rpcvers_t vers; -- version number + * const char *nettype; -- network type + * const struct timeval *tp; -- timeout + */ /* - * Generic client creation routine. Supported protocols are "udp", "tcp" - * and "unix". - * CLIENT * - * clnt_create(host, prog, vers, prot); - * const char *host; -- hostname - * u_long prog; -- program number - * u_long vers; -- version number - * const char *prot; -- protocol + * Generic client creation routine. Supported protocols are which belong + * to the nettype name space. + */ +extern CLIENT *clnt_create_vers(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 -CLIENT * clnt_create(const char *, u_long, u_long, const char *); -__END_DECLS +/* + * Generic client creation routine. Supported protocols are which belong + * to the nettype name space. + */ +extern CLIENT * clnt_create_vers_timed(const char *, const rpcprog_t, + rpcvers_t *, const rpcvers_t, const rpcvers_t, const char *, + const struct timeval *); +/* + * 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 + * const struct timeval *tp -- timeout + */ /* - * TCP based rpc - * CLIENT * - * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) - * struct sockaddr_in *raddr; - * u_long prog; - * u_long version; - * 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(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 (struct sockaddr_in *, - u_long, - u_long, - int *, - u_int, - u_int); -__END_DECLS +/* + * Generic client creation routine. Just like clnt_tp_create(), except + * it takes an additional timeout parameter. + */ +extern CLIENT * clnt_tp_create_timed(const char *, const rpcprog_t, + const rpcvers_t, const struct netconfig *, const struct timeval *); +/* + * const char *hostname; -- hostname + * const rpcprog_t prog; -- program number + * const rpcvers_t vers; -- version number + * const struct netconfig *netconf; -- network config structure + * const struct timeval *tp -- timeout + */ /* - * 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; + * Generic TLI create routine. Only provided for compatibility. + */ + +extern CLIENT *clnt_tli_create(const int, const struct netconfig *, + struct netbuf *, const rpcprog_t, + const rpcvers_t, const u_int, const u_int); +/* + * const register int fd; -- fd + * const struct netconfig *nconf; -- netconfig structure + * 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 + */ + +/* + * Low level clnt create routine for connectionful transports, e.g. tcp. + */ +extern CLIENT *clnt_vc_create(const int, const struct netbuf *, + const rpcprog_t, const rpcvers_t, + u_int, u_int); +/* + * Added for compatibility to old rpc 4.0. Obsoleted by clnt_vc_create(). + */ +extern CLIENT *clntunix_create(struct sockaddr_un *, + u_long, u_long, int *, u_int, 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 */ -__BEGIN_DECLS -extern CLIENT *clntudp_create (struct sockaddr_in *, - u_long, - u_long, - struct timeval, - int *); -extern CLIENT *clntudp_bufcreate (struct sockaddr_in *, - u_long, - u_long, - struct timeval, - int *, - u_int, - u_int); -__END_DECLS +/* + * Low level clnt create routine for connectionless transports, e.g. udp. + */ +extern CLIENT *clnt_dg_create(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 + */ /* - * AF_UNIX based rpc + * 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; - * int *sockp; - * u_int sendsz; - * u_int recvsz; + * u_long vers; */ -__BEGIN_DECLS -extern CLIENT *clntunix_create (struct sockaddr_un *, - u_long, - u_long, - int *, - u_int, - u_int); +extern CLIENT *clnt_raw_create(rpcprog_t, rpcvers_t); + __END_DECLS @@ -383,24 +439,24 @@ __END_DECLS * Print why creation failed */ __BEGIN_DECLS -extern void clnt_pcreateerror(const char *); /* stderr */ -extern char *clnt_spcreateerror(const char *); /* string */ +extern void clnt_pcreateerror(const char *); /* stderr */ +extern char *clnt_spcreateerror(const char *); /* string */ __END_DECLS /* * Like clnt_perror(), but is more verbose in its output */ __BEGIN_DECLS -extern void clnt_perrno (enum clnt_stat); /* stderr */ -extern char *clnt_sperrno (enum clnt_stat); /* string */ +extern void clnt_perrno(enum clnt_stat); /* stderr */ +extern char *clnt_sperrno(enum clnt_stat); /* string */ __END_DECLS /* * Print an English error message, given the client error code */ __BEGIN_DECLS -extern void clnt_perror(CLIENT *, const char *); /* stderr */ -extern char *clnt_sperror(CLIENT *, const char *); /* string */ +extern void clnt_perror(CLIENT *, const char *); /* stderr */ +extern char *clnt_sperror(CLIENT *, const char *); /* string */ __END_DECLS @@ -412,10 +468,90 @@ struct rpc_createerr { struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ }; -extern struct rpc_createerr rpc_createerr; +__BEGIN_DECLS +extern struct rpc_createerr *__rpc_createerr(void); +__END_DECLS +#define rpc_createerr (*(__rpc_createerr())) + +/* + * 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(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)(caddr_t, ...); +__BEGIN_DECLS +extern enum clnt_stat rpc_broadcast(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(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 -#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 0000000000..1d28911e91 --- /dev/null +++ b/include/rpc/clnt_soc.h @@ -0,0 +1,107 @@ +/* + * 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 + * + * $NetBSD: clnt_soc.h,v 1.1 2000/06/02 22:57:55 fvdl Exp $ + * $FreeBSD: src/include/rpc/clnt_soc.h,v 1.2 2002/03/23 17:24:55 imp Exp $ + * $DragonFly$ + */ +/* + * 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 + +#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(struct sockaddr_in *, u_long, u_long, int *, + u_int, u_int); +__END_DECLS + +/* + * Raw (memory) rpc. + */ +__BEGIN_DECLS +extern CLIENT *clntraw_create(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(struct sockaddr_in *, u_long, u_long, + struct timeval, int *); +extern CLIENT *clntudp_bufcreate(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 0000000000..7205ab3596 --- /dev/null +++ b/include/rpc/clnt_stat.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1986 - 1991, 1994, 1996, 1997 by Sun Microsystems, Inc. + * All rights reserved. + * + * @(#)clnt_stat.h>-------1.2>----97/04/28 SMI + * $FreeBSD: src/include/rpc/clnt_stat.h,v 1.2 2001/03/20 08:20:50 alfred Exp $ + * $DragonFly$ + */ + +/* + * clnt_stat.h - Client side remote procedure call enum + * + */ + +#ifndef _RPC_CLNT_STAT_H +#define _RPC_CLNT_STAT_H + +#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 7cdb11db93..e566baee4a 100644 --- a/include/rpc/des_crypt.h +++ b/include/rpc/des_crypt.h @@ -1,6 +1,6 @@ /* * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI - * $FreeBSD: src/include/rpc/des_crypt.h,v 1.2 1999/12/29 05:00:42 peter Exp $ + * $FreeBSD: src/include/rpc/des_crypt.h,v 1.4 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpc/des_crypt.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ * * des_crypt.h, des library routine interface @@ -34,6 +34,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 #include @@ -76,46 +86,22 @@ * Cipher Block Chaining mode */ __BEGIN_DECLS -#ifdef __STDC__ -int cbc_crypt ( 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 +int cbc_crypt( char *, char *, unsigned int, unsigned int, char *); +__END_DECLS /* * Electronic Code Book mode */ -#ifdef __STDC__ -int ecb_crypt ( char *, char *, unsigned int, unsigned int ); -#else -ecb_crypt(/* key, buf, len, mode */); /* - char *key; - char *buf; - unsigned len; - unsigned mode; -*/ -#endif +__BEGIN_DECLS +int ecb_crypt( char *, char *, unsigned int, unsigned int ); __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 ( char *); -#else -void -des_setparity(/* key */); /* - char *key; -*/ -#endif +void des_setparity( char *); __END_DECLS -#endif + +#endif /* _DES_DES_CRYPT_H */ diff --git a/include/rpc/svc_auth.h b/include/rpc/nettype.h similarity index 63% copy from include/rpc/svc_auth.h copy to include/rpc/nettype.h index 409574d692..1a1567f0a0 100644 --- a/include/rpc/svc_auth.h +++ b/include/rpc/nettype.h @@ -26,32 +26,41 @@ * 2550 Garcia Avenue * 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 - * $FreeBSD: src/include/rpc/svc_auth.h,v 1.12 1999/08/27 23:45:05 peter Exp $ - * $DragonFly: src/include/rpc/svc_auth.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ + * $NetBSD: nettype.h,v 1.2 2000/07/06 03:17:19 christos Exp $ + * $FreeBSD: src/include/rpc/nettype.h,v 1.2 2002/03/23 17:24:55 imp Exp $ + * $DragonFly$ */ /* - * svc_auth.h, Service side of rpc authentication. + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * nettype.h, Nettype definitions. + * All for the topmost layer of rpc * - * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef _RPC_SVCAUTH_H -#define _RPC_SVCAUTH_H +#ifndef _RPC_NETTYPE_H +#define _RPC_NETTYPE_H -struct rpc_msg; -struct svc_req; +#include + +#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 -/* - * Server side authenticator - */ __BEGIN_DECLS -extern enum auth_stat _authenticate (struct svc_req *, struct rpc_msg *); -extern int svc_auth_reg (int, enum auth_stat (*)(struct svc_req *, - struct rpc_msg *)); -extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); +void *__rpc_setconf(const char *); +void __rpc_endconf(void *); +struct netconfig *__rpc_getconf(void *); +struct netconfig *__rpc_getconfip(const char *); __END_DECLS -#endif /* !_RPC_SVCAUTH_H */ +#endif /* !_RPC_NETTYPE_H */ diff --git a/include/rpc/pmap_clnt.h b/include/rpc/pmap_clnt.h index 79fcd53323..e92f6c4625 100644 --- a/include/rpc/pmap_clnt.h +++ b/include/rpc/pmap_clnt.h @@ -28,7 +28,8 @@ * * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/pmap_clnt.h,v 1.11 1999/08/27 23:45:04 peter Exp $ + * $NetBSD: pmap_clnt.h,v 1.9 2000/06/02 22:57:55 fvdl Exp $ + * $FreeBSD: src/include/rpc/pmap_clnt.h,v 1.14 2002/04/28 15:18:45 des Exp $ * $DragonFly: src/include/rpc/pmap_clnt.h,v 1.7 2005/11/13 12:27:04 swildner Exp $ */ @@ -62,8 +63,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 __BEGIN_DECLS @@ -73,11 +74,10 @@ struct pmaplist *pmap_getmaps(struct sockaddr_in *); enum clnt_stat pmap_rmtcall(struct sockaddr_in *, u_long, u_long, u_long, xdrproc_t, caddr_t, xdrproc_t, caddr_t, struct timeval, u_long *); -enum clnt_stat clnt_broadcast(u_long, u_long, u_long, xdrproc_t, char *, - xdrproc_t, char *, bool_t (*) (caddr_t, - struct sockaddr_in *)); +enum clnt_stat clnt_broadcast(u_long, u_long, u_long, xdrproc_t, void *, + xdrproc_t, void *, resultproc_t); u_short pmap_getport(struct sockaddr_in *, u_long, u_long, u_int); void pmap_getport_timeout(struct timeval *, struct timeval *); __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 c9ba8c7669..288de2f670 100644 --- a/include/rpc/pmap_prot.h +++ b/include/rpc/pmap_prot.h @@ -28,7 +28,8 @@ * * from: @(#)pmap_prot.h 1.14 88/02/08 SMI * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/pmap_prot.h,v 1.10 1999/08/27 23:45:04 peter Exp $ + * $NetBSD: pmap_prot.h,v 1.8 2000/06/02 22:57:55 fvdl Exp $ + * $FreeBSD: src/include/rpc/pmap_prot.h,v 1.12 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpc/pmap_prot.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ */ @@ -69,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 #define PMAPPORT ((u_short)111) @@ -98,8 +99,9 @@ struct pmaplist { }; __BEGIN_DECLS -extern bool_t xdr_pmap (XDR *, struct pmap *); -extern bool_t xdr_pmaplist (XDR *, struct pmaplist **); +extern bool_t xdr_pmap(XDR *, struct pmap *); +extern bool_t xdr_pmaplist(XDR *, struct pmaplist **); +extern bool_t xdr_pmaplist_ptr(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 b027f409ce..e6f12c9c4d 100644 --- a/include/rpc/pmap_rmt.h +++ b/include/rpc/pmap_rmt.h @@ -28,7 +28,8 @@ * * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/pmap_rmt.h,v 1.10 1999/08/27 23:45:05 peter Exp $ + * $NetBSD: pmap_rmt.h,v 1.7 1998/02/11 23:01:23 lukem Exp $ + * $FreeBSD: src/include/rpc/pmap_rmt.h,v 1.12 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpc/pmap_rmt.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ */ @@ -39,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 struct rmtcallargs { @@ -57,8 +58,8 @@ struct rmtcallres { }; __BEGIN_DECLS -extern bool_t xdr_rmtcall_args (XDR *, struct rmtcallargs *); -extern bool_t xdr_rmtcallres (XDR *, struct rmtcallres *); +bool_t xdr_rmtcall_args(XDR *, struct rmtcallargs *); +bool_t xdr_rmtcallres(XDR *, struct rmtcallres *); __END_DECLS -#endif /* !_RPC_PMAPRMT_H */ +#endif /* !_RPC_PMAP_RMT_H_ */ diff --git a/lib/libc/rpc/rpc_commondata.c b/include/rpc/raw.h similarity index 70% copy from lib/libc/rpc/rpc_commondata.c copy to include/rpc/raw.h index 06227653dd..d0e980cc28 100644 --- a/lib/libc/rpc/rpc_commondata.c +++ b/include/rpc/raw.h @@ -26,17 +26,34 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/rpc_commondata.c,v 1.7 1999/08/28 00:00:45 peter Exp $ - * $DragonFly: src/lib/libc/rpc/rpc_commondata.c,v 1.2 2003/06/17 04:26:45 dillon Exp $ + * from: @(#)raw.h>1.11>---94/04/25 SMI + * from: @(#)raw.h 1.2 88/10/25 SMI + * $NetBSD: raw.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/raw.h,v 1.1 2001/03/19 12:49:47 alfred Exp $ + * $DragonFly$ + + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ -#include +#ifndef _RPC_RAW_H_ +#define _RPC_RAW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + /* - * This file should only contain common data (global data) that is exported - * by public interfaces + * raw.h + * + * Raw interface + * The common memory area over which they will communicate */ -struct opaque_auth _null_auth; -fd_set svc_fdset; -int svc_maxfd = -1; -struct rpc_createerr rpc_createerr; +extern char *__rpc_rawcombuf; + +#ifdef __cplusplus +} +#endif + +#endif /* _RPC_RAW_H_ */ diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h index 999f06de82..66efa3c4a8 100644 --- a/include/rpc/rpc.h +++ b/include/rpc/rpc.h @@ -28,7 +28,8 @@ * * from: @(#)rpc.h 1.9 88/02/08 SMI * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC - * $FreeBSD: src/include/rpc/rpc.h,v 1.12 2000/01/26 09:02:40 shin Exp $ + * $NetBSD: rpc.h,v 1.13 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/rpc.h,v 1.17 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpc/rpc.h,v 1.6 2007/12/04 20:59:15 swildner Exp $ */ @@ -42,6 +43,7 @@ #define _RPC_RPC_H #include /* some typedefs */ +#include #include /* external data representation interfaces */ @@ -66,35 +68,41 @@ #include /* service manager and multiplexer */ #include /* 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 included in . - */ -/* routines for parsing /etc/rpc */ +/* Portmapper client, server, and protocol headers */ +#include +#include -struct rpcent { - char *r_name; /* name of server for this rpc program */ - char **r_aliases; /* alias list */ - int r_number; /* rpc program number */ -}; +#ifndef _KERNEL +#include /* rpcbind interface functions */ +#endif + +#include __BEGIN_DECLS -int callrpc(char *, int, int, int, xdrproc_t, char *, xdrproc_t, - char *); -int registerrpc(int, int, int, char *(*)(void), xdrproc_t, - xdrproc_t); +int get_myaddress(struct sockaddr_in *); +int bindresvport(int, struct sockaddr_in *); +int registerrpc(int, int, int, char *(*)(char [UDPMSGSIZE]), xdrproc_t, + xdrproc_t); +int callrpc(const char *, int, int, int, xdrproc_t, void *, xdrproc_t, + void *); +int getrpcport(char *, int, int, int); + +char *taddr2uaddr(const struct netconfig *, const struct netbuf *); +struct netbuf *uaddr2taddr(const struct netconfig *, const char *); -struct rpcent *getrpcbyname(char *); -struct rpcent *getrpcbynumber(int); -struct rpcent *getrpcent(void); -int getrpcport(char *, int, int, int); -void setrpcent(int); -void endrpcent(void); +struct sockaddr; +int bindresvport_sa(int, struct sockaddr *); +__END_DECLS -int bindresvport(int, struct sockaddr_in *); -int bindresvport_sa(int, struct sockaddr *); -int get_myaddress(struct sockaddr_in *); +/* + * 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(const struct netconfig *); +int __rpc_nconf2sockinfo(const struct netconfig *, struct __rpc_sockinfo *); +int __rpc_fd2sockinfo(int, struct __rpc_sockinfo *); +u_int __rpc_get_t_size(int, int, int); __END_DECLS #endif /* !_RPC_RPC_H */ diff --git a/include/rpc/rpc_com.h b/include/rpc/rpc_com.h index 2cf5995d2d..132e8e427f 100644 --- a/include/rpc/rpc_com.h +++ b/include/rpc/rpc_com.h @@ -25,6 +25,11 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * from: @(#)rpc_com.h 1.11 93/07/05 SMI + * $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ + * $FreeBSD: src/include/rpc/rpc_com.h,v 1.6 2003/01/16 07:13:51 mbr Exp $ + * $DragonFly$ */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. @@ -36,20 +41,12 @@ * */ -#ifndef _RPC_RPCCOM_H -#define _RPC_RPCCOM_H +#ifndef _RPC_RPC_COM_H_ +#define _RPC_RPC_COM_H_ -/* From: #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ +#include -#ifdef __cplusplus -extern "C" { -#endif -/* - * 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. @@ -57,22 +54,31 @@ extern "C" { #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(int); +extern int __rpc_dtbsize(void); +extern int _rpc_dtablesize(void); +extern struct netconfig * __rpcgettp(int); +extern int __rpc_get_default_domain(char **); + +char *__rpc_taddr2uaddr_af(int, const struct netbuf *); +struct netbuf *__rpc_uaddr2taddr_af(int, const char *); +int __rpc_fixup_addr(struct netbuf *, const struct netbuf *); +int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **); +int __rpc_seman2socktype(int); +int __rpc_socktype2seman(int); +void *rpc_nullproc(CLIENT *); +int __rpc_sockisbound(int); + +struct netbuf *__rpcb_findaddr(rpcprog_t, rpcvers_t, const struct netconfig *, + const char *, CLIENT **); +bool_t rpc_control(int,void *); + +char *_get_next_token(char *, int); -#ifdef __cplusplus -} -#endif +__END_DECLS -#endif /* _RPC_RPCCOM_H */ +#endif /* _RPC_RPC_COM_H_ */ diff --git a/include/rpc/rpc_msg.h b/include/rpc/rpc_msg.h index cc1c38f877..183708b2cc 100644 --- a/include/rpc/rpc_msg.h +++ b/include/rpc/rpc_msg.h @@ -28,7 +28,8 @@ * * from: @(#)rpc_msg.h 1.7 86/07/16 SMI * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/rpc_msg.h,v 1.12 1999/08/27 23:45:05 peter Exp $ + * $NetBSD: rpc_msg.h,v 1.11 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/rpc_msg.h,v 1.15 2003/01/01 18:48:42 schweikh Exp $ * $DragonFly: src/include/rpc/rpc_msg.h,v 1.4 2007/12/04 20:59:15 swildner Exp $ */ @@ -39,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) /* @@ -89,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; @@ -109,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; @@ -135,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 */ }; @@ -166,7 +167,7 @@ __BEGIN_DECLS * XDR *xdrs; * struct rpc_msg *cmsg; */ -extern bool_t xdr_callmsg (XDR *, struct rpc_msg *); +extern bool_t xdr_callmsg(XDR *, struct rpc_msg *); /* * XDR routine to pre-serialize the static part of a rpc message. @@ -174,7 +175,7 @@ extern bool_t xdr_callmsg (XDR *, struct rpc_msg *); * XDR *xdrs; * struct rpc_msg *cmsg; */ -extern bool_t xdr_callhdr (XDR *, struct rpc_msg *); +extern bool_t xdr_callhdr(XDR *, struct rpc_msg *); /* * XDR routine to handle a rpc reply. @@ -182,7 +183,7 @@ extern bool_t xdr_callhdr (XDR *, struct rpc_msg *); * XDR *xdrs; * struct rpc_msg *rmsg; */ -extern bool_t xdr_replymsg (XDR *, struct rpc_msg *); +extern bool_t xdr_replymsg(XDR *, struct rpc_msg *); /* * XDR routine to handle an accepted rpc reply. @@ -206,8 +207,7 @@ extern bool_t xdr_rejected_reply(XDR *, struct rejected_reply *); * struct rpc_msg *msg; * struct rpc_err *error; */ -struct rpc_err; -extern void _seterr_reply (struct rpc_msg *, struct rpc_err *); +extern void _seterr_reply(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 0000000000..c6ec587595 --- /dev/null +++ b/include/rpc/rpcb_clnt.h @@ -0,0 +1,86 @@ +/* + * 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 + * + * from: @(#)rpcb_clnt.h 1.13 94/04/25 SMI + * from: rpcb_clnt.h 1.3 88/12/05 SMI + * $NetBSD: rpcb_clnt.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/rpcb_clnt.h,v 1.2 2002/03/23 17:24:55 imp Exp $ + * $DragonFly$ + */ +/* + * 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_ + + +#include +#include + +__BEGIN_DECLS +extern bool_t rpcb_set(const rpcprog_t, const rpcvers_t, + const struct netconfig *, const struct netbuf *); +extern bool_t rpcb_unset(const rpcprog_t, const rpcvers_t, + const struct netconfig *); +extern rpcblist *rpcb_getmaps(const struct netconfig *, const char *); +extern enum clnt_stat rpcb_rmtcall(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(const rpcprog_t, const rpcvers_t, + const struct netconfig *, struct netbuf *, + const char *); +extern bool_t rpcb_gettime(const char *, time_t *); +extern char *rpcb_taddr2uaddr(struct netconfig *, struct netbuf *); +extern struct netbuf *rpcb_uaddr2taddr(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 0000000000..db0b630540 --- /dev/null +++ b/include/rpc/rpcb_prot.x @@ -0,0 +1,555 @@ +%/* +% * $FreeBSD: src/include/rpc/rpcb_prot.x,v 1.3 2002/03/13 10:29:06 obrien Exp $ +% * $DragonFly$ +% * +% * 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 +% * . 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/rpc_com.h b/include/rpc/rpcent.h similarity index 54% copy from include/rpc/rpc_com.h copy to include/rpc/rpcent.h index 2cf5995d2d..41e34e4d8d 100644 --- a/include/rpc/rpc_com.h +++ b/include/rpc/rpcent.h @@ -5,74 +5,65 @@ * 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 + * + * from: @(#)rpcent.h 1.13 94/04/25 SMI + * from: @(#)rpcent.h 1.1 88/12/06 SMI + * $NetBSD: rpcent.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/rpcent.h,v 1.2 2002/03/23 17:24:55 imp Exp $ + * $DragonFly$ */ /* * 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 + * rpcent.h, + * For converting rpc program numbers to names etc. * */ -#ifndef _RPC_RPCCOM_H -#define _RPC_RPCCOM_H +#ifndef _RPC_RPCENT_H_ +#define _RPC_RPCENT_H_ -/* From: #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ -#ifdef __cplusplus -extern "C" { -#endif - -/* - * 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 +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; -#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 +__BEGIN_DECLS +extern struct rpcent *getrpcbyname_r(const char *, struct rpcent *, + char *, int); +extern struct rpcent *getrpcbynumber_r(int, struct rpcent *, char *, int); +extern struct rpcent *getrpcent_r(struct rpcent *, char *, int); -#ifdef __cplusplus -} -#endif +/* Old interfaces that return a pointer to a static area; MT-unsafe */ +extern struct rpcent *getrpcbyname(char *); +extern struct rpcent *getrpcbynumber(int); +extern struct rpcent *getrpcent(void); +extern void setrpcent(int); +extern void endrpcent(void); +__END_DECLS -#endif /* _RPC_RPCCOM_H */ +#endif /* !_RPC_RPCENT_H_ */ diff --git a/include/rpc/svc.h b/include/rpc/svc.h index d5aa807c5d..cda56d101a 100644 --- a/include/rpc/svc.h +++ b/include/rpc/svc.h @@ -26,16 +26,17 @@ * 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 - * $FreeBSD: src/include/rpc/svc.h,v 1.16 1999/12/29 05:00:43 peter Exp $ + * from: @(#)svc.h 1.35 88/12/17 SMI + * from: @(#)svc.h 1.27 94/04/25 SMI + * $NetBSD: svc.h,v 1.17 2000/06/02 22:57:56 fvdl Exp $ + * $FreeBSD: src/include/rpc/svc.h,v 1.24 2003/06/15 10:32:01 mbr Exp $ * $DragonFly: src/include/rpc/svc.h,v 1.4 2008/05/19 10:19:49 corecode Exp $ */ /* * 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 @@ -65,49 +66,83 @@ * parameters, struct svc_req * and SVCXPRT *, defined below. */ +/* + * Service control requests + */ +#define SVCGET_VERSQUIET 1 +#define SVCSET_VERSQUIET 2 +#define SVCGET_CONNMAXREC 3 +#define SVCSET_CONNMAXREC 4 + +/* + * Operations for rpc_control(). + */ +#define RPC_SVC_CONNMAXREC_SET 0 /* set max rec size, enable nonblock */ +#define RPC_SVC_CONNMAXREC_GET 1 + 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) (struct __rpc_svcxprt *, - struct rpc_msg *); + bool_t (*xp_recv)(struct __rpc_svcxprt *, struct rpc_msg *); /* get transport status */ - enum xprt_stat (*xp_stat) (struct __rpc_svcxprt *); + enum xprt_stat (*xp_stat)(struct __rpc_svcxprt *); /* get arguments */ - bool_t (*xp_getargs) (struct __rpc_svcxprt *, xdrproc_t, - caddr_t); + bool_t (*xp_getargs)(struct __rpc_svcxprt *, xdrproc_t, + void *); /* send reply */ - bool_t (*xp_reply) (struct __rpc_svcxprt *, - struct rpc_msg *); + bool_t (*xp_reply)(struct __rpc_svcxprt *, struct rpc_msg *); /* free mem allocated for args */ - bool_t (*xp_freeargs) (struct __rpc_svcxprt *, xdrproc_t, - caddr_t); + bool_t (*xp_freeargs)(struct __rpc_svcxprt *, xdrproc_t, + void *); /* destroy this struct */ - void (*xp_destroy) (struct __rpc_svcxprt *); + void (*xp_destroy)(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)(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) /* * Operations defined on an SVCXPRT handle @@ -115,7 +150,7 @@ typedef struct __rpc_svcxprt { * SVCXPRT *xprt; * struct rpc_msg *msg; * xdrproc_t xargs; - * caddr_t argsp; + * void * argsp; */ #define SVC_RECV(xprt, msg) \ (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) @@ -147,44 +182,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 (SVCXPRT *, u_long, u_long, - void (*) (struct svc_req *, SVCXPRT *), int); +extern bool_t svc_reg(SVCXPRT *, const rpcprog_t, const rpcvers_t, + void (*)(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 (u_long, u_long); +extern void svc_unreg(const rpcprog_t, const rpcvers_t); __END_DECLS /* @@ -194,7 +221,7 @@ __END_DECLS * SVCXPRT *xprt; */ __BEGIN_DECLS -extern void xprt_register (SVCXPRT *); +extern void xprt_register(SVCXPRT *); __END_DECLS /* @@ -204,12 +231,10 @@ __END_DECLS * SVCXPRT *xprt; */ __BEGIN_DECLS -extern void xprt_unregister (SVCXPRT *); +extern void xprt_unregister(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 @@ -237,14 +262,17 @@ __END_DECLS */ __BEGIN_DECLS -extern bool_t svc_sendreply (SVCXPRT *, xdrproc_t, char *); -extern void svcerr_decode (SVCXPRT *); -extern void svcerr_weakauth (SVCXPRT *); -extern void svcerr_noproc (SVCXPRT *); -extern void svcerr_progvers (SVCXPRT *, u_long, u_long); -extern void svcerr_auth (SVCXPRT *, enum auth_stat); -extern void svcerr_noprog (SVCXPRT *); -extern void svcerr_systemerr (SVCXPRT *); +extern bool_t svc_sendreply(SVCXPRT *, xdrproc_t, void *); +extern void svcerr_decode(SVCXPRT *); +extern void svcerr_weakauth(SVCXPRT *); +extern void svcerr_noproc(SVCXPRT *); +extern void svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t); +extern void svcerr_auth(SVCXPRT *, enum auth_stat); +extern void svcerr_noprog(SVCXPRT *); +extern void svcerr_systemerr(SVCXPRT *); +extern int rpc_reg(rpcprog_t, rpcvers_t, rpcproc_t, + char *(*)(char *), xdrproc_t, xdrproc_t, + char *); __END_DECLS /* @@ -263,64 +291,142 @@ __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(void); +__END_DECLS __BEGIN_DECLS -extern void svc_getreq (int); -extern void svc_getreqset (fd_set *); -extern void svc_getreqset2 (fd_set *, int); /* XXX: nonstd, undoc */ -extern void svc_run (void); +extern void svc_getreq(int); +extern void svc_getreqset(fd_set *); +extern void svc_getreq_common(int); +struct pollfd; +extern void svc_getreq_poll(struct pollfd *, int); + +extern void svc_run(void); +extern void svc_exit(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(void (*)(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 (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 (int); -extern SVCXPRT *svcudp_bufcreate (int, u_int, u_int); -__END_DECLS + +extern SVCXPRT *svc_tp_create(void (*)(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(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 (int, u_int, u_int); -extern SVCXPRT *svcfd_create (int, u_int, u_int); -__END_DECLS /* - * AF_UNIX socket based rpc. + * Connectionless and connectionful create routines */ -__BEGIN_DECLS -extern SVCXPRT *svcunix_create (int, u_int, u_int, char *); -extern SVCXPRT *svcunixfd_create (int, u_int, u_int); + +extern SVCXPRT *svc_vc_create(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 + */ + +/* + * Added for compatibility to old rpc 4.0. Obsoleted by svc_vc_create(). + */ +extern SVCXPRT *svcunix_create(int, u_int, u_int, char *); + +extern SVCXPRT *svc_dg_create(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(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 + */ + +/* + * Added for compatibility to old rpc 4.0. Obsoleted by svc_fd_create(). + */ +extern SVCXPRT *svcunixfd_create(int, u_int, u_int); + +/* + * Memory based rpc (for speed check and testing) + */ +extern SVCXPRT *svc_raw_create(void); + +/* + * svc_dg_enable_cache() enables the cache on dg transports. + */ +int svc_dg_enablecache(SVCXPRT *, const u_int); + +int __rpc_get_local_uid(SVCXPRT *_transp, uid_t *_uid); + __END_DECLS + +/* for backward compatibility */ +#include + #endif /* !_RPC_SVC_H */ diff --git a/include/rpc/svc_auth.h b/include/rpc/svc_auth.h index 409574d692..8cce85c00b 100644 --- a/include/rpc/svc_auth.h +++ b/include/rpc/svc_auth.h @@ -28,7 +28,8 @@ * * from: @(#)svc_auth.h 1.6 86/07/16 SMI * from: @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/svc_auth.h,v 1.12 1999/08/27 23:45:05 peter Exp $ + * $NetBSD: svc_auth.h,v 1.8 2000/06/02 22:57:57 fvdl Exp $ + * $FreeBSD: src/include/rpc/svc_auth.h,v 1.15 2008/09/09 14:15:55 dfr Exp $ * $DragonFly: src/include/rpc/svc_auth.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ */ @@ -38,20 +39,19 @@ * 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 (struct svc_req *, struct rpc_msg *); -extern int svc_auth_reg (int, enum auth_stat (*)(struct svc_req *, - struct rpc_msg *)); -extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); +extern struct svc_auth_ops svc_auth_null_ops; + +extern enum auth_stat _authenticate(struct svc_req *, struct rpc_msg *); +extern int svc_auth_reg(int, enum auth_stat (*)(struct svc_req *, + struct rpc_msg *)); + __END_DECLS -#endif /* !_RPC_SVCAUTH_H */ +#endif /* !_RPC_SVC_AUTH_H_ */ diff --git a/lib/libc/rpc/pmap_prot.c b/include/rpc/svc_dg.h similarity index 62% copy from lib/libc/rpc/pmap_prot.c copy to include/rpc/svc_dg.h index 0ab4da6189..060a986b91 100644 --- a/lib/libc/rpc/pmap_prot.c +++ b/include/rpc/svc_dg.h @@ -26,31 +26,27 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro - * @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_prot.c,v 1.6 1999/08/28 00:00:42 peter Exp $ - * $DragonFly: src/lib/libc/rpc/pmap_prot.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ + * $NetBSD: svc_dg.h,v 1.1 2000/06/02 23:11:16 fvdl Exp $ + * $FreeBSD: src/include/rpc/svc_dg.h,v 1.1 2001/03/19 12:49:47 alfred Exp $ + * $DragonFly$ */ /* - * pmap_prot.c - * Protocol for the local binder service, or pmap. - * - * Copyright (C) 1984, Sun Microsystems, Inc. + * 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. */ -#include -#include -#include - - -bool_t -xdr_pmap(XDR *xdrs, struct pmap *regs) -{ +/* + * 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 */ +}; - if (xdr_u_long(xdrs, ®s->pm_prog) && - xdr_u_long(xdrs, ®s->pm_vers) && - xdr_u_long(xdrs, ®s->pm_prot)) - return (xdr_u_long(xdrs, ®s->pm_port)); - return (FALSE); -} +#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 0000000000..e16e57ec06 --- /dev/null +++ b/include/rpc/svc_soc.h @@ -0,0 +1,116 @@ +/* + * 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 + * + * from: @(#)svc_soc.h 1.11 94/04/25 SMI + * from: svc_soc.h 1.8 89/05/01 SMI + * $NetBSD: svc_soc.h,v 1.1 2000/06/02 22:57:57 fvdl Exp $ + * $FreeBSD: src/include/rpc/svc_soc.h,v 1.2 2002/03/23 17:24:55 imp Exp $ + * $DragonFly$ + */ +/* + * 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 + +/* + * 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(SVCXPRT *, u_long, u_long, + void (*)(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(u_long, u_long); +__END_DECLS + + +/* + * Memory based rpc for testing and timing. + */ +__BEGIN_DECLS +extern SVCXPRT *svcraw_create(void); +__END_DECLS + + +/* + * Udp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcudp_create(int); +extern SVCXPRT *svcudp_bufcreate(int, u_int, u_int); +extern int svcudp_enablecache(SVCXPRT *, u_long); +__END_DECLS + + +/* + * Tcp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svctcp_create(int, u_int, u_int); +__END_DECLS + +/* + * Fd based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcfd_create(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 37be7e7731..d9d92761fa 100644 --- a/include/rpc/types.h +++ b/include/rpc/types.h @@ -28,7 +28,8 @@ * * from: @(#)types.h 1.18 87/07/24 SMI * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC - * $FreeBSD: src/include/rpc/types.h,v 1.9 1999/08/27 23:45:06 peter Exp $ + * $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ + * $FreeBSD: src/sys/rpc/types.h,v 1.10 2001/03/19 12:49:47 alfred Exp $ * $DragonFly: src/include/rpc/types.h,v 1.2 2003/06/17 04:25:58 dillon Exp $ */ @@ -38,8 +39,18 @@ #ifndef _RPC_TYPES_H #define _RPC_TYPES_H -#define bool_t int32_t -#define enum_t int32_t +#include + +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 @@ -52,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 -#endif #include +#include + +/* + * The netbuf structure is defined here, because FreeBSD / NetBSD only use + * it inside the RPC code. It's in 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 1e1ca7e353..92ee67b119 100644 --- a/include/rpc/xdr.h +++ b/include/rpc/xdr.h @@ -28,7 +28,8 @@ * * from: @(#)xdr.h 1.19 87/04/22 SMI * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/xdr.h,v 1.14.2.1 2003/03/20 12:59:55 jedgar Exp $ + * $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ + * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $ * $DragonFly: src/include/rpc/xdr.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ */ @@ -98,27 +99,28 @@ 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) (struct __rpc_xdr *, long *); - /* put a long to underlying stream */ - bool_t (*x_putlong) (struct __rpc_xdr *, long *); - /* get some bytes from underlying stream */ - bool_t (*x_getbytes) (struct __rpc_xdr *, caddr_t, u_int); - /* put some bytes to underlying stream */ - bool_t (*x_putbytes) (struct __rpc_xdr *, caddr_t, u_int); + bool_t (*x_getlong)(struct __rpc_xdr *, long *); + /* put a long to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, const long *); + /* get some bytes from " */ + bool_t (*x_getbytes)(struct __rpc_xdr *, char *, u_int); + /* put some bytes to " */ + bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, u_int); /* returns bytes off from beginning */ - u_int (*x_getpostn) (struct __rpc_xdr *); + u_int (*x_getpostn)(struct __rpc_xdr *); /* lets you reposition the stream */ - bool_t (*x_setpostn) (struct __rpc_xdr *, u_int); + bool_t (*x_setpostn)(struct __rpc_xdr *, u_int); /* buf quick ptr to buffered data */ - int32_t *(*x_inline) (struct __rpc_xdr *, u_int); + int32_t *(*x_inline)(struct __rpc_xdr *, u_int); /* free privates of this xdr_stream */ - void (*x_destroy) (struct __rpc_xdr *); + void (*x_destroy)(struct __rpc_xdr *); + bool_t (*x_control)(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 */ u_int x_handy; /* extra private word */ } XDR; @@ -131,12 +133,12 @@ typedef struct __rpc_xdr { * allocate dynamic storage of the appropriate size and return it. */ #ifdef _KERNEL -typedef bool_t (*xdrproc_t) (XDR *, void *, u_int); +typedef bool_t (*xdrproc_t)(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) (/* XDR *, void *, u_int */); +typedef bool_t (*xdrproc_t)(XDR *, ...); #endif /* @@ -144,7 +146,7 @@ typedef bool_t (*xdrproc_t) (/* XDR *, void *, u_int */); * * XDR *xdrs; * long *longp; - * caddr_t addr; + * char * addr; * u_int len; * u_int pos; */ @@ -158,6 +160,29 @@ typedef bool_t (*xdrproc_t) (/* 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) \ @@ -190,10 +215,25 @@ typedef bool_t (*xdrproc_t) (/* 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 - * a entry with a null procedure pointer. The xdr_union routine gets + * an entry with a null procedure pointer. The xdr_union routine gets * the discriminant value and then searches the array of structures * for a matching value. If a match is found the associated xdr routine * is called to handle that part of the union. If there is @@ -221,8 +261,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)) @@ -230,46 +275,50 @@ 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. */ __BEGIN_DECLS -extern bool_t xdr_void (void); -extern bool_t xdr_int (XDR *, int *); -extern bool_t xdr_u_int (XDR *, u_int *); -extern bool_t xdr_long (XDR *, long *); -extern bool_t xdr_u_long (XDR *, u_long *); -extern bool_t xdr_short (XDR *, short *); -extern bool_t xdr_u_short (XDR *, u_short *); -extern bool_t xdr_int16_t (XDR *, int16_t *); -extern bool_t xdr_u_int16_t (XDR *, u_int16_t *); -extern bool_t xdr_int32_t (XDR *, int32_t *); -extern bool_t xdr_u_int32_t (XDR *, u_int32_t *); -extern bool_t xdr_int64_t (XDR *, int64_t *); -extern bool_t xdr_u_int64_t (XDR *, u_int64_t *); -extern bool_t xdr_bool (XDR *, bool_t *); -extern bool_t xdr_enum (XDR *, enum_t *); -extern bool_t xdr_array (XDR *, char **, u_int *, u_int, u_int, xdrproc_t); -extern bool_t xdr_bytes (XDR *, char **, u_int *, u_int); -extern bool_t xdr_opaque (XDR *, caddr_t, u_int); -extern bool_t xdr_string (XDR *, char **, u_int); -extern bool_t xdr_union (XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t); -extern unsigned long xdr_sizeof (xdrproc_t, void *); -extern bool_t xdr_char (XDR *, char *); -extern bool_t xdr_u_char (XDR *, u_char *); -extern bool_t xdr_vector (XDR *, char *, u_int, u_int, xdrproc_t); -extern bool_t xdr_float (XDR *, float *); -extern bool_t xdr_double (XDR *, double *); -extern bool_t xdr_reference (XDR *, caddr_t *, u_int, xdrproc_t); -extern bool_t xdr_pointer (XDR *, caddr_t *, u_int, xdrproc_t); -extern bool_t xdr_wrapstring (XDR *, char **); -extern void xdr_free (xdrproc_t, char *); +extern bool_t xdr_void(void); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, u_int *); +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, u_long *); +extern bool_t xdr_short(XDR *, short *); +extern bool_t xdr_u_short(XDR *, u_short *); +extern bool_t xdr_int16_t(XDR *, int16_t *); +extern bool_t xdr_u_int16_t(XDR *, u_int16_t *); +extern bool_t xdr_int32_t(XDR *, int32_t *); +extern bool_t xdr_u_int32_t(XDR *, u_int32_t *); +extern bool_t xdr_int64_t(XDR *, int64_t *); +extern bool_t xdr_u_int64_t(XDR *, u_int64_t *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int); +extern bool_t xdr_opaque(XDR *, char *, u_int); +extern bool_t xdr_string(XDR *, char **, u_int); +extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, u_char *); +extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_quadruple(XDR *, long double *); +extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); +extern void xdr_free(xdrproc_t, void *); +extern bool_t xdr_hyper(XDR *, quad_t *); +extern bool_t xdr_u_hyper(XDR *, u_quad_t *); +extern bool_t xdr_longlong_t(XDR *, quad_t *); +extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *); __END_DECLS /* @@ -282,7 +331,7 @@ struct netobj { char *n_bytes; }; typedef struct netobj netobj; -extern bool_t xdr_netobj (XDR *, struct netobj *); +extern bool_t xdr_netobj(XDR *, struct netobj *); /* * These are the public routines for the various implementations of @@ -290,26 +339,27 @@ extern bool_t xdr_netobj (XDR *, struct netobj *); */ __BEGIN_DECLS /* XDR using memory buffers */ -extern void xdrmem_create (XDR *, char *, u_int, enum xdr_op); +extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op); -#ifdef _STDIO_H_ /* XDR using stdio library */ -extern void xdrstdio_create (XDR *, FILE *, enum xdr_op); +#ifdef _STDIO_H_ +extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); #endif /* XDR pseudo records for tcp */ -extern void xdrrec_create (XDR *, u_int, u_int, char *, - int (*) (caddr_t, caddr_t, int), - int (*) (caddr_t, caddr_t, int)); +extern void xdrrec_create(XDR *, u_int, u_int, void *, + int (*)(void *, void *, int), + int (*)(void *, void *, int)); /* make end of xdr record */ -extern bool_t xdrrec_endofrecord (XDR *, int); +extern bool_t xdrrec_endofrecord(XDR *, int); /* move to beginning of next record */ -extern bool_t xdrrec_skiprecord (XDR *); +extern bool_t xdrrec_skiprecord(XDR *); /* true if no more input */ -extern bool_t xdrrec_eof (XDR *); +extern bool_t xdrrec_eof(XDR *); +extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int); __END_DECLS #endif /* !_RPC_XDR_H */ diff --git a/include/rpcsvc/bootparam_prot.x b/include/rpcsvc/bootparam_prot.x index 3244162262..dc28fa8aca 100644 --- a/include/rpcsvc/bootparam_prot.x +++ b/include/rpcsvc/bootparam_prot.x @@ -28,7 +28,7 @@ * * @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro * @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC - * $FreeBSD: src/include/rpcsvc/bootparam_prot.x,v 1.5 1999/08/27 23:45:07 peter Exp $ + * $FreeBSD: src/include/rpcsvc/bootparam_prot.x,v 1.7 2003/05/04 02:51:42 obrien Exp $ * $DragonFly: src/include/rpcsvc/bootparam_prot.x,v 1.2 2003/06/17 04:25:58 dillon Exp $ */ @@ -48,7 +48,6 @@ %#include %#include %#include -%#include #endif const MAX_MACHINE_NAME = 255; diff --git a/include/rpcsvc/nis.x b/include/rpcsvc/nis.x index 76b2e18ff6..e4708fed40 100644 --- a/include/rpcsvc/nis.x +++ b/include/rpcsvc/nis.x @@ -27,7 +27,7 @@ % * 2550 Garcia Avenue % * Mountain View, California 94043 % * -% * $FreeBSD: src/include/rpcsvc/nis.x,v 1.3.2.1 2001/03/05 12:47:48 obrien Exp $ +% * $FreeBSD: src/include/rpcsvc/nis.x,v 1.6 2003/05/04 02:51:42 obrien Exp $ % * $DragonFly: src/include/rpcsvc/nis.x,v 1.2 2003/06/17 04:25:58 dillon Exp $ % */ @@ -188,7 +188,7 @@ struct ping_args { /* * These are the type of entries that are stored in the transaction log, * note that modifications will appear as two entries, for names, they have - * a "OLD" entry followed by a "NEW" entry. For entries in tables, there + * an "OLD" entry followed by a "NEW" entry. For entries in tables, there * is a remove followed by an add. It is done this way so that we can read * the log backwards to back out transactions and forwards to propogate * updated. diff --git a/include/rpcsvc/nislib.h b/include/rpcsvc/nislib.h index 14b8768aa2..25970bdc14 100644 --- a/include/rpcsvc/nislib.h +++ b/include/rpcsvc/nislib.h @@ -26,6 +26,7 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * + * $FreeBSD: src/include/rpcsvc/nislib.h,v 1.4 2002/03/23 17:24:55 imp Exp $ * $DragonFly: src/include/rpcsvc/nislib.h,v 1.2 2004/02/25 15:12:54 joerg Exp $ */ @@ -35,8 +36,7 @@ /* * This file contains the interfaces that are visible in the SunOS 5.x - * implementation of NIS Plus. When using C++ the defined __cplusplus and - * __STDC__ should both be true. + * implementation of NIS Plus. */ #ifndef _RPCSVC_NISLIB_H diff --git a/include/rpcsvc/nlm_prot.x b/include/rpcsvc/nlm_prot.x index 0651fc9ed4..24fb605aa3 100644 --- a/include/rpcsvc/nlm_prot.x +++ b/include/rpcsvc/nlm_prot.x @@ -1,7 +1,8 @@ %/* % * @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro % * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC -% * $FreeBSD: src/include/rpcsvc/nlm_prot.x,v 1.8.2.1 2001/08/01 06:39:36 alfred Exp $ +% * $NetBSD: nlm_prot.x,v 1.6 2000/06/07 14:30:15 bouyer Exp $ +% * $FreeBSD: src/include/rpcsvc/nlm_prot.x,v 1.9 2001/03/19 12:49:48 alfred Exp $ % * $DragonFly: src/include/rpcsvc/nlm_prot.x,v 1.2 2003/06/17 04:25:58 dillon Exp $ % */ @@ -15,7 +16,6 @@ #ifdef RPC_HDR %#define LM_MAXSTRLEN 1024 %#define MAXNAMELEN LM_MAXSTRLEN+1 -%#include #endif /* @@ -33,8 +33,8 @@ struct nlm_holder { bool exclusive; int svid; netobj oh; - u_int32_t l_offset; - u_int32_t l_len; + unsigned l_offset; + unsigned l_len; }; union nlm_testrply switch (nlm_stats stat) { @@ -62,9 +62,9 @@ struct nlm_lock { string caller_name; netobj fh; /* identify a file */ netobj oh; /* identify owner of a lock */ - int32_t svid; /* generated from pid for svid */ - u_int32_t l_offset; - u_int32_t l_len; + int svid; /* generated from pid for svid */ + unsigned l_offset; + unsigned l_len; }; struct nlm_lockargs { @@ -73,24 +73,24 @@ struct nlm_lockargs { bool exclusive; struct nlm_lock alock; bool reclaim; /* used for recovering locks */ - int32_t state; /* specify local status monitor state */ + int state; /* specify local status monitor state */ }; 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; }; @@ -132,64 +132,80 @@ struct nlm_shareargs { struct nlm_shareres { netobj cookie; nlm_stats stat; - int32_t sequence; + int sequence; }; struct nlm_notify { string name; - int32_t state; + long state; }; +#ifdef RPC_HDR +%/* definitions for NLM version 4 */ +#endif enum nlm4_stats { - nlm4_granted = 0, - nlm4_denied = 1, - nlm4_denied_nolocks = 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 + 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; - int32_t svid; - netobj oh; - u_int64_t l_offset; - u_int64_t l_len; + bool exclusive; + u_int32_t svid; + netobj oh; + u_int64_t l_offset; + u_int64_t l_len; }; -struct nlm4_stat { - nlm4_stats stat; +struct nlm4_lock { + string caller_name; + netobj fh; + netobj oh; + u_int32_t svid; + u_int64_t l_offset; + u_int64_t l_len; +}; + +struct nlm4_share { + string caller_name; + netobj fh; + netobj oh; + fsh_mode mode; + fsh_access access; }; union nlm4_testrply switch (nlm4_stats stat) { - case nlm4_denied: + case nlm_denied: struct nlm4_holder holder; default: void; }; -struct nlm4_res { - netobj cookie; - nlm4_stat stat; -}; - struct nlm4_testres { netobj cookie; nlm4_testrply stat; }; +struct nlm4_testargs { + netobj cookie; + bool exclusive; + struct nlm4_lock alock; +}; -struct nlm4_lock { - string caller_name; - netobj fh; /* identify a file */ - netobj oh; /* identify owner of a lock */ - int32_t svid; /* generated from pid for svid */ - int64_t l_offset; - int64_t l_len; +struct nlm4_res { + netobj cookie; + nlm4_stat stat; }; struct nlm4_lockargs { @@ -198,36 +214,21 @@ struct nlm4_lockargs { bool exclusive; struct nlm4_lock alock; bool reclaim; /* used for recovering locks */ - int32_t state; /* specify local status monitor state */ + int state; /* specify local status monitor state */ }; - struct nlm4_cancargs { - netobj cookie; + netobj cookie; bool block; bool exclusive; struct nlm4_lock alock; }; -struct nlm4_testargs { - netobj cookie; - bool exclusive; - struct nlm4_lock alock; -}; - struct nlm4_unlockargs { - netobj cookie; + netobj cookie; struct nlm4_lock alock; }; -struct nlm4_share { - string caller_name; - netobj fh; - netobj oh; - fsh_mode mode; - fsh_access access; -}; - struct nlm4_shareargs { netobj cookie; nlm4_share share; @@ -237,12 +238,18 @@ struct nlm4_shareargs { struct nlm4_shareres { netobj cookie; nlm4_stats stat; - int32_t sequence; + int sequence; }; -struct nlm4_notify { - string name; - int32_t state; +/* + * 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; /* name of host */ + int state; /* new state */ + opaque priv[16]; /* private data */ }; /* @@ -250,6 +257,10 @@ struct nlm4_notify { */ 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; @@ -285,39 +296,25 @@ program NLM_PROG { void NLM_FREE_ALL(nlm_notify) = 23; } = 3; - version NLM4_VERS { - void NLMPROC4_NULL(void) = 0; - - nlm4_testres NLMPROC4_TEST(struct nlm4_testargs) = 1; - - nlm4_res NLMPROC4_LOCK(struct nlm4_lockargs) = 2; - - nlm4_res NLMPROC4_CANCEL(struct nlm4_cancargs) = 3; - nlm4_res NLMPROC4_UNLOCK(struct nlm4_unlockargs) = 4; - - /* - * remote lock manager call-back to grant lock - */ - nlm4_res NLMPROC4_GRANTED(struct nlm4_testargs)= 5; - /* - * message passing style of requesting lock - */ - void NLMPROC4_TEST_MSG(struct nlm4_testargs) = 6; - void NLMPROC4_LOCK_MSG(struct nlm4_lockargs) = 7; - void NLMPROC4_CANCEL_MSG(struct nlm4_cancargs) =8; - void NLMPROC4_UNLOCK_MSG(struct nlm4_unlockargs) = 9; - void NLMPROC4_GRANTED_MSG(struct nlm4_testargs) = 10; - void NLMPROC4_TEST_RES(nlm4_testres) = 11; - void NLMPROC4_LOCK_RES(nlm4_res) = 12; - void NLMPROC4_CANCEL_RES(nlm4_res) = 13; - void NLMPROC4_UNLOCK_RES(nlm4_res) = 14; - void NLMPROC4_GRANTED_RES(nlm4_res) = 15; - - nlm4_shareres NLMPROC4_SHARE(nlm4_shareargs) = 20; - nlm4_shareres NLMPROC4_UNSHARE(nlm4_shareargs) = 21; - nlm4_res NLMPROC4_NM_LOCK(nlm4_lockargs) = 22; - void NLMPROC4_FREE_ALL(nlm4_notify) = 23; + 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/pmap_prot.x b/include/rpcsvc/pmap_prot.x index fb167b859c..c3a6f036b6 100644 --- a/include/rpcsvc/pmap_prot.x +++ b/include/rpcsvc/pmap_prot.x @@ -27,6 +27,7 @@ % * Mountain View, California 94043 % * % * @(#)pmap_prot.x 1.6 94/04/29 SMI +% * $FreeBSD: src/include/rpcsvc/pmap_prot.x,v 1.3 2003/05/04 02:51:42 obrien Exp $ % * $DragonFly: src/include/rpcsvc/pmap_prot.x,v 1.2 2003/06/17 04:25:58 dillon Exp $ % */ %/* @@ -143,11 +144,7 @@ typedef pm__list *pmaplist_ptr; /* results of PMAPPROC_DUMP */ %#ifdef __cplusplus %extern "C" { %#endif -%#ifdef __STDC__ %extern bool_t xdr_pmaplist(XDR *, pmaplist**); -%#else /* K&R C */ -%bool_t xdr_pmaplist(); -%#endif %#ifdef __cplusplus %} %#endif @@ -263,11 +260,7 @@ program PMAPPROG { % long unsigned pm_port; %}; %typedef struct pmap PMAP; -%#ifdef __STDC__ %extern bool_t xdr_pmap (XDR *, struct pmap *); -%#else -%extern bool_t xdr_pmap (); -%#endif % %struct pmaplist { % struct pmap pml_map; diff --git a/include/rpcsvc/rstat.x b/include/rpcsvc/rstat.x index c0505da815..c60a902b47 100644 --- a/include/rpcsvc/rstat.x +++ b/include/rpcsvc/rstat.x @@ -28,7 +28,7 @@ * * @(#)rstat.x 1.2 87/09/18 Copyr 1987 Sun Micro * @(#)rstat.x 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/include/rpcsvc/rstat.x,v 1.6 1999/08/27 23:45:11 peter Exp $ + * $FreeBSD: src/include/rpcsvc/rstat.x,v 1.8 2003/05/04 02:51:42 obrien Exp $ * $DragonFly: src/include/rpcsvc/rstat.x,v 1.2 2003/06/17 04:25:58 dillon Exp $ */ @@ -145,3 +145,10 @@ program RSTATPROG { RSTATPROC_HAVEDISK(void) = 2; } = 1; } = 100001; + +#ifdef RPC_HDR +% +%enum clnt_stat rstat(char *, struct statstime *); +%int havedisk(char *); +% +#endif diff --git a/include/rpcsvc/yp_prot.h b/include/rpcsvc/yp_prot.h index 8ccef6907e..96caa57e57 100644 --- a/include/rpcsvc/yp_prot.h +++ b/include/rpcsvc/yp_prot.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/include/rpcsvc/yp_prot.h,v 1.10.2.1 2002/02/15 00:46:53 des Exp $ + * $FreeBSD: src/include/rpcsvc/yp_prot.h,v 1.13 2005/12/06 02:01:06 peter Exp $ * $DragonFly: src/include/rpcsvc/yp_prot.h,v 1.3 2004/12/15 09:44:47 dillon Exp $ */ @@ -96,7 +96,7 @@ typedef struct { struct ypmap_parms { char *domain; char *map; - u_long ordernum; + u_int ordernum; char *owner; }; @@ -113,9 +113,9 @@ struct ypreq_nokey { struct ypreq_xfr { struct ypmap_parms map_parms; - u_long transid; - u_long proto; - u_short port; + u_int transid; + u_int proto; + u_int port; }; #define ypxfr_domain map_parms.domain #define ypxfr_map map_parms.map @@ -123,33 +123,33 @@ struct ypreq_xfr { #define ypxfr_owner map_parms.owner struct ypresp_val { - u_long status; + u_int status; datum valdat; }; struct ypresp_key_val { - u_long status; + u_int status; datum keydat; datum valdat; }; struct ypresp_master { - u_long status; + u_int status; char *master; }; struct ypresp_order { - u_long status; - u_long ordernum; + u_int status; + u_int ordernum; }; struct ypmaplist { - char ypml_name[YPMAXMAP + 1]; + char *ypml_name; struct ypmaplist *ypml_next; }; struct ypresp_maplist { - u_long status; + u_int status; struct ypmaplist *list; }; @@ -241,7 +241,7 @@ struct ypbind_binding { struct ypbind_resp { enum ypbind_resptype ypbind_status; union { - u_long ypbind_error; + u_int ypbind_error; struct ypbind_binding ypbind_bindinfo; } ypbind_respbody; }; @@ -257,7 +257,7 @@ struct ypbind_resp { struct ypbind_setdom { char ypsetdom_domain[YPMAXDOMAIN + 1]; struct ypbind_binding ypsetdom_binding; - u_short ypsetdom_vers; + u_int ypsetdom_vers; }; #define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr #define ypsetdom_port ypsetdom_binding.ypbind_binding_port @@ -282,8 +282,8 @@ struct ypbind_setdom { #define YPPUSHPROC_XFRRESP ((u_long)1) struct yppushresp_xfr { - u_long transid; - u_long status; + u_int transid; + u_int status; }; /* yppush status value in yppushresp_xfr.status */ diff --git a/include/rpcsvc/ypclnt.h b/include/rpcsvc/ypclnt.h index e93d4017a9..dd5d096086 100644 --- a/include/rpcsvc/ypclnt.h +++ b/include/rpcsvc/ypclnt.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/include/rpcsvc/ypclnt.h,v 1.11.2.1 2002/02/15 00:46:53 des Exp $ + * $FreeBSD: src/include/rpcsvc/ypclnt.h,v 1.16 2003/10/26 16:35:11 peter Exp $ * $DragonFly: src/include/rpcsvc/ypclnt.h,v 1.7 2005/04/27 12:26:59 joerg Exp $ */ @@ -67,6 +67,8 @@ struct ypall_callback { }; struct dom_binding; +struct ypmaplist; +struct ypall_callback; __BEGIN_DECLS int yp_bind(char *); diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c index f43a49601d..5c6ae7b2b4 100644 --- a/lib/libc/gen/_pthread_stubs.c +++ b/lib/libc/gen/_pthread_stubs.c @@ -23,15 +23,21 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/_pthread_stubs.c,v 1.1 2001/01/24 12:59:20 deischen Exp $ + * $FreeBSD: src/lib/libc/gen/_pthread_stubs.c,v 1.5 2001/06/11 23:18:22 iedowse Exp $ * $DragonFly: src/lib/libc/gen/_pthread_stubs.c,v 1.4 2005/05/09 12:43:40 davidxu Exp $ */ +#include #include +#include +int _pthread_cond_init_stub(pthread_cond_t *, const pthread_condattr_t *); +int _pthread_cond_signal_stub(pthread_cond_t *); +int _pthread_cond_wait_stub(pthread_cond_t *, pthread_mutex_t *); void *_pthread_getspecific_stub(pthread_key_t); int _pthread_key_create_stub(pthread_key_t *, void (*)(void *)); int _pthread_key_delete_stub(pthread_key_t); +int _pthread_main_np_stub(void); int _pthread_mutex_destroy_stub(pthread_mutex_t *); int _pthread_mutex_init_stub(pthread_mutex_t *, const pthread_mutexattr_t *); @@ -42,7 +48,16 @@ int _pthread_mutexattr_init_stub(pthread_mutexattr_t *); int _pthread_mutexattr_destroy_stub(pthread_mutexattr_t *); int _pthread_mutexattr_settype_stub(pthread_mutexattr_t *, int); int _pthread_once_stub(pthread_once_t *, void (*)(void)); +int _pthread_rwlock_init_stub(pthread_rwlock_t *, + const pthread_rwlockattr_t *); +int _pthread_rwlock_destroy_stub(pthread_rwlock_t *); +int _pthread_rwlock_rdlock_stub(pthread_rwlock_t *); +int _pthread_rwlock_tryrdlock_stub(pthread_rwlock_t *); +int _pthread_rwlock_trywrlock_stub(pthread_rwlock_t *); +int _pthread_rwlock_unlock_stub(pthread_rwlock_t *); +int _pthread_rwlock_wrlock_stub(pthread_rwlock_t *); int _pthread_setspecific_stub(pthread_key_t, const void *); +int _pthread_sigmask_stub(int, const sigset_t *, sigset_t *); /* define a null pthread structure just to satisfy _pthread_self */ struct pthread { @@ -59,20 +74,51 @@ static struct pthread main_thread; * between application locks and libc locks (threads holding the * latter can't be allowed to exit/terminate). */ -__weak_reference(_pthread_getspecific_stub,_pthread_getspecific); -__weak_reference(_pthread_key_create_stub,_pthread_key_create); -__weak_reference(_pthread_key_delete_stub,_pthread_key_delete); -__weak_reference(_pthread_mutex_destroy_stub,_pthread_mutex_destroy); -__weak_reference(_pthread_mutex_init_stub,_pthread_mutex_init); -__weak_reference(_pthread_mutex_lock_stub,_pthread_mutex_lock); -__weak_reference(_pthread_mutex_trylock_stub,_pthread_mutex_trylock); -__weak_reference(_pthread_mutex_unlock_stub,_pthread_mutex_unlock); -__weak_reference(_pthread_mutexattr_init_stub,_pthread_mutexattr_init); -__weak_reference(_pthread_mutexattr_destroy_stub,_pthread_mutexattr_destroy); -__weak_reference(_pthread_mutexattr_settype_stub,_pthread_mutexattr_settype); -__weak_reference(_pthread_once_stub,_pthread_once); -__weak_reference(_pthread_setspecific_stub,_pthread_setspecific); -__weak_reference(_pthread_self_stub,_pthread_self); +__weak_reference(_pthread_cond_init_stub, _pthread_cond_init); +__weak_reference(_pthread_cond_signal_stub, _pthread_cond_signal); +__weak_reference(_pthread_cond_wait_stub, _pthread_cond_wait); +__weak_reference(_pthread_getspecific_stub, _pthread_getspecific); +__weak_reference(_pthread_key_create_stub, _pthread_key_create); +__weak_reference(_pthread_key_delete_stub, _pthread_key_delete); +__weak_reference(_pthread_main_np_stub, _pthread_main_np); +__weak_reference(_pthread_mutex_destroy_stub, _pthread_mutex_destroy); +__weak_reference(_pthread_mutex_init_stub, _pthread_mutex_init); +__weak_reference(_pthread_mutex_lock_stub, _pthread_mutex_lock); +__weak_reference(_pthread_mutex_trylock_stub, _pthread_mutex_trylock); +__weak_reference(_pthread_mutex_unlock_stub, _pthread_mutex_unlock); +__weak_reference(_pthread_mutexattr_init_stub, _pthread_mutexattr_init); +__weak_reference(_pthread_mutexattr_destroy_stub, _pthread_mutexattr_destroy); +__weak_reference(_pthread_mutexattr_settype_stub, _pthread_mutexattr_settype); +__weak_reference(_pthread_once_stub, _pthread_once); +__weak_reference(_pthread_self_stub, _pthread_self); +__weak_reference(_pthread_rwlock_init_stub, _pthread_rwlock_init); +__weak_reference(_pthread_rwlock_rdlock_stub, _pthread_rwlock_rdlock); +__weak_reference(_pthread_rwlock_tryrdlock_stub, _pthread_rwlock_tryrdlock); +__weak_reference(_pthread_rwlock_trywrlock_stub, _pthread_rwlock_trywrlock); +__weak_reference(_pthread_rwlock_unlock_stub, _pthread_rwlock_unlock); +__weak_reference(_pthread_rwlock_wrlock_stub, _pthread_rwlock_wrlock); +__weak_reference(_pthread_setspecific_stub, _pthread_setspecific); +__weak_reference(_pthread_sigmask_stub, _pthread_sigmask); + +int +_pthread_cond_init_stub(pthread_cond_t *cond __unused, + const pthread_condattr_t *cond_attr __unused) +{ + return (0); +} + +int +_pthread_cond_signal_stub(pthread_cond_t *cond __unused) +{ + return (0); +} + +int +_pthread_cond_wait_stub(pthread_cond_t *cond __unused, + pthread_mutex_t *mutex __unused) +{ + return (0); +} void * _pthread_getspecific_stub(pthread_key_t key __unused) @@ -93,6 +139,12 @@ _pthread_key_delete_stub(pthread_key_t key __unused) return (0); } +int +_pthread_main_np_stub(void) +{ + return (-1); +} + int _pthread_mutex_destroy_stub(pthread_mutex_t *mattr __unused) { @@ -150,7 +202,50 @@ _pthread_once_stub(pthread_once_t *once_control __unused, return (0); } -struct pthread * +int +_pthread_rwlock_init_stub(pthread_rwlock_t *rwlock __unused, + const pthread_rwlockattr_t *attr __unused) +{ + return (0); +} + +int +_pthread_rwlock_destroy_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +int +_pthread_rwlock_rdlock_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +int +_pthread_rwlock_tryrdlock_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +int +_pthread_rwlock_trywrlock_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +int +_pthread_rwlock_unlock_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +int +_pthread_rwlock_wrlock_stub(pthread_rwlock_t *rwlock __unused) +{ + return (0); +} + +pthread_t _pthread_self_stub(void) { return (&main_thread); @@ -162,3 +257,9 @@ _pthread_setspecific_stub(pthread_key_t key __unused, return (0); } +int +_pthread_sigmask_stub(int how __unused, const sigset_t *set __unused, + sigset_t *oset __unused) +{ + return (0); +} diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 91fd5cbe68..508fcd8dd6 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -59,6 +59,7 @@ #define listen _listen #define nanosleep _nanosleep #define open _open +#define poll _poll #define pthread_atfork _pthread_atfork #define pthread_attr_destroy _pthread_attr_destroy #define pthread_attr_get_np _pthread_attr_get_np @@ -220,7 +221,6 @@ #define msync _msync #define nfssvc _nfssvc #define pause _pause -#define poll _poll #define sched_yield _sched_yield #define sendfile _sendfile #define shutdown _shutdown diff --git a/lib/libc/include/reentrant.h b/lib/libc/include/reentrant.h new file mode 100644 index 0000000000..c9feac4d4f --- /dev/null +++ b/lib/libc/include/reentrant.h @@ -0,0 +1,136 @@ +/*- + * 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: src/lib/libc/include/reentrant.h,v 1.3 2004/02/25 21:03:45 green Exp $ + * $DragonFly$ + */ + +/* + * 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 +#include +#include "libc_private.h" + +#define mutex_t pthread_mutex_t +#define cond_t pthread_cond_t +#define rwlock_t pthread_rwlock_t +#define once_t pthread_once_t + +#define thread_key_t pthread_key_t +#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER +#define ONCE_INITIALIZER PTHREAD_ONCE_INIT + +#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_broadcast(m) if (__isthreaded) \ + _pthread_cond_broadcast(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_once(o, i) _pthread_once(o, i) +#define thr_self() _pthread_self() +#define thr_exit(x) _pthread_exit(x) +#define thr_main() _pthread_main_np() diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index 3d3d454082..8b20b57ea6 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -54,6 +54,7 @@ #undef listen #undef nanosleep #undef open +#undef poll #undef pthread_atfork #undef pthread_attr_destroy #undef pthread_attr_get_np @@ -207,7 +208,6 @@ #undef msync #undef nfssvc #undef pause -#undef poll #undef pthread_rwlock_destroy #undef pthread_rwlock_init #undef pthread_rwlock_rdlock diff --git a/lib/libc/rpc/LICENSE b/lib/libc/rpc/LICENSE new file mode 100644 index 0000000000..5b9220ef2d --- /dev/null +++ b/lib/libc/rpc/LICENSE @@ -0,0 +1,336 @@ +$FreeBSD: src/lib/libc/rpc/LICENSE,v 1.1 2002/07/11 16:23:04 alfred Exp $ +$DragonFly$ + +Sun Industry Standards Source License 1.0 + +DEFINITIONS + +1.1. "Commercial Use" means distribution or otherwise +making the Original Code available to a third party. + +1.2. "Contributor Version" means the combination of the +Original Code, and the Modifications made by that particular +Contributor. + +1.3. "Electronic Distribution Mechanism" means a mechanism +generally accepted in the software development community for +the electronic transfer of data. + +1.4. "Executable" means Original Code in any form other +than Source Code. + +1.5. "Initial Developer" means the individual or entity +identified as the Initial Developer in the Source Code +notice required by 2 (Exhibit A) + +1.6. "Larger Work" means a work which combines Original +Code or portions thereof with code not governed by the terms +of this License. + +1.7. "License" means this document. + +1.8. "Licensable" means having the right to grant, to the +maximum extent possible, whether at the time of the initial +grant or subsequently acquired, any and all of the rights +conveyed herein. + +1.9. "Modifications" means any addition to or deletion from +the substance or structure of either the Original Code or +any previous Modifications. A Modification is: + +A. Any addition to or deletion from the contents of a file +containing Original Code or previous Modifications. + +B. Any new file that contains any part of the Original Code +or previous Modifications. . + +1.10. "Original Code" means Source Code of computer +software code which is described in the Source Code notice +required by Exhibit A as Original Code. + +1.11. "Patent Claims" means any patent claims, now owned or +hereafter acquired, including without limitation, method, +process, and apparatus claims, in any patent Licensable by +grantor. + +1.12. "Source Code" means the preferred form of the +Original Code for making modifications to it, including all +modules it contains, plus any associated interface +definition files, or scripts used to control compilation and +installation of an Executable. + +1.13. "Standards" means the standard identified in Exhibit +B or a subsequent version of such standard. + +1.14. "You" or "Your" means an individual or a legal entity +exercising rights under, and complying with all of the terms +of, this License or a future version of this License issued +under Section 6.1. For legal entities, "You" includes any +entity which controls, is controlled by, or is under common +control with You. For purposes of this definition, +"control" means (a) the power, direct or indirect, to cause +the direction or management of such entity, whether by +contract or otherwise, or (b) ownership of more than fifty +percent (50%) of the outstanding shares or beneficial +ownership of such entity. + +2.0 SOURCE CODE LICENSE + +2.1 The Initial Developer Grant: The Initial Developer +hereby grants You a world-wide, royalty-free, non-exclusive +license, subject to third party intellectual property +claims: + +a) under intellectual property rights (other than patent or +trademark) Licensable by Initial Developer to use, +reproduce, modify, display, perform, sub license and +distribute the Original Code (or portions thereof )with or +without Modifications, and/or as part of a Larger Work; and + +b) under Patents Claims infringed by the making, using or +selling of Original Code, to make, have made, use, practice, +sell, and offer for sale, and/or otherwise dispose of the +Original Code (or portions thereof). + +c) the licenses granted in this Section 2.1(a ) and (b) are +effective on the date Initial Developer first distributes +Original Code under the terms of this License. + +d) Notwithstanding Section 2.1(b )above, no patent license +is granted: 1) for code that You delete from the Original +Code; 2) separate from the Original Code; or 3) for +infringements caused by: i) the modification of the +Original Code or + +ii) the combination of the Original Code with other software +or devices, including but not limited to Modifications. + +3.0 DISTRIBUTION OBLIGATIONS + +3.1 Application of License. The Source Code version of +Original Code may be distributed only under the terms of +this License or a future version of this License released +under Section 6.1, and You must include a copy of this +License with every copy of the Source Code You distribute. +You may not offer or impose any terms on any Source Code +version that alters or restricts the applicable version of +this License or the recipient's rights hereunder. Your +license for shipment of the Contributor Version is +conditioned upon your full compliance with this Section. +The Modifications which you create must comply with all +requirements set out by the Standards body in effect 120 +days before You ship the Contributor Version. In the event +that the Modifications do not meet such requirements, You +agree to publish (i) any deviation from the Standards +protocol resulting from implementation of your Modifications +and (ii) a reference implementation of Your Modifications, +and to make any such deviation and reference implementation +available to all third parties under the same terms as the +license on a royalty free basis within thirty (30) days of +Your first customer shipment of Your Modifications. + +3.2 Required Notices. You must duplicate the notice in +Exhibit A in each file of the Source Code. If it is not +possible to put such notice in a particular Source Code file +due to its structure, then You must include such notice in a +location (such as a relevant directory ) where a user would +be likely to look for such a notice. If You created one or +more Modifications ) You may add your name as a Contributor +to the notice described in Exhibit A. You must also +duplicate this License in any documentation for the Source +Code where You describe recipients' rights or ownership +rights relating to Initial Code. You may choose to offer, +and to charge a fee for, warranty, support, indemnity or +liability obligations to one or more recipients of Your +version of the Code. However, You may do so only + +on Your own behalf, and not on behalf of the Initial +Developer. You must make it absolutely clear than any such +warranty, support, indemnity or liability obligation is +offered by You alone, and You hereby agree to indemnify the +Initial Developer for any liability incurred by the Initial +Developer as a result of warranty, support, indemnity or +liability terms You offer. + +3.3 Distribution of Executable Versions. You may distribute +Original Code in Executable and Source form only if the +requirements of Section 3.1 and 3.2 have been met for that +Original Code, and if You include a notice stating that the +Source Code version of the Original Code is available under +the terms of this License. The notice must be conspicuously +included in any notice in an Executable or Source versions, +related documentation or collateral in which You describe +recipients' rights relating to the Original Code. You may +distribute the Executable and Source versions of Your +version of the Code or ownership rights under a license of +Your choice, which may contain terms different from this +License, provided that You are in compliance with the terms +of this License. If You distribute the Executable and +Source versions under a different license You must make it +absolutely clear that any terms which differ from this +License are offered by You alone, not by the Initial +Developer . You hereby agree to indemnify the Initial +Developer for any liability incurred by the Initial +Developer as a result of any such terms You offer . + +3.4 Larger Works. You may create a Larger Work by combining +Original Code with other code not governed by the terms of +this License and distribute the Larger Work as a single +product. In such a case, You must make sure the +requirements of this License are fulfilled for the Original +Code. + +4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION + +If it is impossible for You to comply with any of the terms +of this License with respect to some or all of the Original +Code due to statute, judicial order, or regulation then You +must: + +a) comply with the terms of this License to the maximum +extent possible; and + +b) describe the limitations and the code they affect. Such +description must be included in the LEGAL file described in +Section 3.2 and must be included with all distributions of +the Source Code. Except to the extent prohibited by statute +or regulation, such description must be sufficiently +detailed for a recipient of ordinary skill to be able to +understand it. + +5.0 APPLICATION OF THIS LICENSE This License applies to code +to which the Initial Developer has attached the notice in +Exhibit A and to related Modifications as set out in Section +3.1. + +6.0 VERSIONS OF THE LICENSE + +6.1 New Versions. Sun Microsystems, Inc. Sun may publish +revised and/or new versions of the License from time to +time. Each version will be given a distinguishing version +number . + +6.2 Effect of New Versions. Once Original Code has been +published under a particular version of the License, You may +always continue to use it under the terms of that version. +You may also choose to use such Original Code under the +terms of any subsequent version of the License published by +Sun. No one other than Sun has the right to modify the +terms applicable to Original Code. + +7. DISCLAIMER OF W ARRANTY. ORIGINAL CODE IS PROVIDED +UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF +DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR +NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY +ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE +INITIAL DEVELOPER )ASSUME THE COST OF ANY NECESSARY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF +WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO +USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT +UNDER THIS DISCLAIMER. + +8.0 TERMINATION + +8.1 This License and the rights granted hereunder will +terminate automatically if You fail to comply with terms +herein and fail to cure such breach within 30 days of +becoming aware of the breach. All sublicenses to the +Original Code which are properly granted shall survive any +termination of this License. Provisions which, by their +nature, must remain in effect beyond the termination of this +License shall survive. + +8.2 .In the event of termination under Section 8.1 above, +all end user license agreements (excluding distributors and +resellers) which have been validly granted by You or any +distributor hereunder prior to termination shall survive +termination. + +9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO +LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE) ,CONTRACT, +OR OTHER WISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER +CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY +SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR +ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF GOOD WILL, WORK STOPPAGE, COMPUTER FAILURE OR +MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR +LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE +POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY +SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY +RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT +APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME +JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND +LIMITATION MAY NOT APPLY TO YOU. + +10.0 U .S. GOVERNMENT END USERS U.S. Government: If this +Software is being acquired by or on behalf of the U.S. +Government or by a U.S. Government prime contractor or +subcontractor (at any tier), then the Government's rights in +the Software and accompanying documentation shall be only as +set forth in this license; this is in accordance with 48 C.F +.R. 227.7201 through 227.7202-4 (for Department of Defense +(DoD) acquisitions )and with 48 C.F.R.2.101 and 12.212( for +non-DoD acquisitions). + +11.0 MISCELLANEOUS This License represents the complete +agreement concerning subject matter hereof. If any +provision of this License is held to be unenforceable, such +provision shall be reformed only to the extent necessary to +make it enforceable. This License shall be governed by +California law provisions (except to the extent applicable +law, if any, provides otherwise), excluding its +conflict-of-law provisions. With respect to disputes in +which at least one party is a citizen of, or an entity +chartered or registered to do business in the United States +of America, any litigation relating to this License shall be +subject to the jurisdiction of the Federal Courts of the +Northern District of California, with venue lying in Santa +Clara County, California, with the losing party responsible +for costs, including without limitation, court costs and +reasonable attorneys fees and expenses. The application of +the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. Any law +or regulation which provides that the language of a contract +shall be construed against the drafter shall not apply to +this License. + +EXHIBIT A - Sun Standards + +"The contents of this file are subject to the Sun Standards +License Version 1.0 the (the "License";) You may not use +this file except in compliance with the License. You may +obtain a copy of the License at +_______________________________. + + Software distributed under the License is distributed on +an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either +express or implied. See the License for the specific +language governing rights and limitations under the License. + +The Original Code is Copyright 1998 by Sun Microsystems, Inc + +The Initial Developer of the Original Code is: Sun +Microsystems, Inc. + +Portions created by _____________________________ are +Copyright ______________________________. + +All Rights Reserved. + +Contributors: ______________________________________. + +EXHIBIT B - Sun Standards + +The Standard is defined as the following IETF RFCs: + +RFC1831: RPC: Remote Procedure Call Protocol Specification +Version 2 RFC1832: XDR: External Data REpresentation +Standard RFC1833: Binding Protocols for ONC RPC Version 2 +RFC2078: Generic Security Service Application Program +Interface, Version 2 RFC2203: RPCSEC_GSS Protocol +Specification RFC2695: Authentication Mechanisms for ONC RPC diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc index d4dbe5d1ad..37f53a8c07 100644 --- a/lib/libc/rpc/Makefile.inc +++ b/lib/libc/rpc/Makefile.inc @@ -1,26 +1,33 @@ -# @(#)Makefile 5.11 (Berkeley) 9/6/90 -# $FreeBSD: src/lib/libc/rpc/Makefile.inc,v 1.17.2.2 2001/04/25 10:04:08 ru Exp $ +# @(#)Makefile 5.11 (Berkeley) 9/6/90 +# $FreeBSD: src/lib/libc/rpc/Makefile.inc,v 1.27 2005/09/11 20:59:52 stefanf Exp $ # $DragonFly: src/lib/libc/rpc/Makefile.inc,v 1.3 2005/08/05 23:43:19 swildner Exp $ .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 +# 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 -CFLAGS+= -DBROKEN_DES +CFLAGS+= -DBROKEN_DES -DPORTMAP -DDES_BUILTIN +CFLAGS+= -I${.CURDIR}/rpc CLEANFILES+= crypt_clnt.c crypt_xdr.c crypt.h @@ -38,81 +45,137 @@ crypt.h: ${RPCDIR}/crypt.x .if ${LIB} == "c" -MAN+= bindresvport.3 des_crypt.3 getrpcent.3 getrpcport.3 publickey.3 rpc.3 \ - rpc_secure.3 rtime.3 -MAN+= publickey.5 rpc.5 - +MAN+= 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 publickey.3 rpc_secure.3 \ + rtime.3 +MAN+= netconfig.5 publickey.5 rpc.5 MLINKS+= bindresvport.3 bindresvport_sa.3 \ des_crypt.3 cbc_crypt.3 \ des_crypt.3 des_setparity.3 \ des_crypt.3 ecb_crypt.3 \ + getnetconfig.3 endnetconfig.3 \ + getnetconfig.3 freenetconfigent.3 \ + getnetconfig.3 getnetconfigent.3 \ + getnetconfig.3 nc_perror.3 \ + getnetconfig.3 nc_sperror.3 \ + getnetconfig.3 setnetconfig.3 \ + getnetpath.3 endnetpath.3 \ + getnetpath.3 setnetpath.3 \ getrpcent.3 endrpcent.3 \ getrpcent.3 getrpcbyname.3 \ getrpcent.3 getrpcbynumber.3 \ getrpcent.3 setrpcent.3 \ publickey.3 getpublickey.3 \ publickey.3 getsecretkey.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 + 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_freeres.3 \ + rpc_clnt_calls.3 clnt_geterr.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_broadcast.3 \ + rpc_clnt_calls.3 rpc_broadcast_exp.3 \ + rpc_clnt_calls.3 rpc_call.3 \ + rpc_clnt_create.3 clnt_control.3 \ + rpc_clnt_create.3 clnt_create.3 \ + rpc_clnt_create.3 clnt_create_timed.3 \ + rpc_clnt_create.3 clnt_create_vers.3 \ + rpc_clnt_create.3 clnt_create_vers_timed.3 \ + rpc_clnt_create.3 clnt_destroy.3 \ + rpc_clnt_create.3 clnt_dg_create.3 \ + rpc_clnt_create.3 clnt_pcreateerror.3 \ + rpc_clnt_create.3 clnt_raw_create.3 \ + rpc_clnt_create.3 clnt_spcreateerror.3 \ + rpc_clnt_create.3 clnt_tli_create.3 \ + rpc_clnt_create.3 clnt_tp_create.3 \ + rpc_clnt_create.3 clnt_tp_create_timed.3 \ + rpc_clnt_create.3 clnt_vc_create.3 \ + rpc_secure.3 authdes_create.3 \ + rpc_secure.3 authdes_getucred.3 \ + rpc_secure.3 getnetname.3 \ + rpc_secure.3 host2netname.3 \ + rpc_secure.3 key_decryptsession.3 \ + rpc_secure.3 key_encryptsession.3 \ + rpc_secure.3 key_gendes.3 \ + rpc_secure.3 key_setsecret.3 \ + rpc_secure.3 netname2host.3 \ + rpc_secure.3 netname2user.3 \ + rpc_secure.3 user2netname.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 clntunix_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 svcunix_create.3 \ + rpc_soc.3 svcunixfd_create.3 \ + rpc_soc.3 xdr_pmap.3 \ + rpc_soc.3 xdr_pmaplist.3 \ + rpc_svc_calls.3 __svc_getcallercreds.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_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_destroy.3 \ + rpc_svc_create.3 svc_dg_create.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_auth_reg.3 \ + rpc_svc_reg.3 svc_reg.3 \ + rpc_svc_reg.3 svc_unreg.3 \ + rpc_svc_reg.3 xprt_register.3 \ + rpc_svc_reg.3 xprt_unregister.3 \ + rpcbind.3 rpcb_getaddr.3 \ + rpcbind.3 rpcb_getmaps.3 \ + rpcbind.3 rpcb_gettime.3 \ + rpcbind.3 rpcb_rmtcall.3 \ + rpcbind.3 rpcb_set.3 \ + rpcbind.3 rpcb_unset.3 .endif diff --git a/lib/libc/rpc/README b/lib/libc/rpc/README index ad9d70f990..0e7b630ccc 100644 --- a/lib/libc/rpc/README +++ b/lib/libc/rpc/README @@ -1,233 +1,176 @@ -RPCSRC 4.0 7/11/89 +$FreeBSD: src/lib/libc/rpc/README,v 1.2 2001/03/19 12:49:50 alfred Exp $ +$DragonFly$ + +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. + + uts/common/rpc RPC header files - demo/ Various demonstration services - demo/dir Remote directory lister - demo/msg Remote console message delivery service - demo/sort Remote sort service - 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. +BUILD INSTRUCTIONS - man/ Manual pages for RPC library, rpcgen, and utilities. +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: - rpc/ The RPC and XDR library. SEE BELOW - FOR BUGFIX TO 4.2BSD COMPILER. + setenv SRC /usr/src/tirpcsrc (csh) +or + SRC=/usr/src/tirpcsrc; export SRC (sh) - rpcgen/ The RPC Language compiler (for .x files) +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. - rpcsvc/ Service definition files for various services and the - server and client code for the Remote Status service. +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: - 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. + make install ROOT=/opt/onc -BUILD INSTRUCTIONS +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 ba00abb8c9..008fec1862 100644 --- a/lib/libc/rpc/auth_des.c +++ b/lib/libc/rpc/auth_des.c @@ -27,7 +27,7 @@ * Mountain View, California 94043 * * @(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI - * $FreeBSD: src/lib/libc/rpc/auth_des.c,v 1.3 1999/08/28 00:00:32 peter Exp $ + * $FreeBSD: src/lib/libc/rpc/auth_des.c,v 1.10 2006/02/27 22:10:58 deischen Exp $ * $DragonFly: src/lib/libc/rpc/auth_des.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ /* @@ -36,54 +36,54 @@ /* * auth_des.c, client-side implementation of DES authentication */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include #include #include #include #include #include +#include #include -#include #include #include -#include /* XXX: just to get htonl() and ntohl() */ +#include +#include #include #undef NIS #include +#include "un-namespace.h" +#include "mt_misc.h" -extern bool_t __rpc_get_time_offset ( struct timeval *, nis_server *, - char *, char **, struct sockaddr_in * ); -extern int rtime ( struct sockaddr_in *, struct timeval *, struct timeval *); -extern bool_t xdr_authdes_cred ( XDR *, struct authdes_cred * ); -extern bool_t xdr_authdes_verf ( 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 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 ( 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 *" */ @@ -93,11 +93,11 @@ struct ad_private { char *ad_servername; /* server's full name */ u_int ad_servernamelen; /* length of name, rounded up */ u_int ad_window; /* client specified window */ - bool_t ad_dosync; /* synchronize? */ - struct sockaddr ad_syncaddr; /* remote host to synch with */ + bool_t ad_dosync; /* synchronize? */ + struct netbuf ad_syncaddr; /* remote host to synch with */ char *ad_timehost; /* remote host to synch with */ struct timeval ad_timediff; /* server's time - client's time */ - u_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 */ @@ -107,104 +107,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(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); - 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(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; @@ -215,12 +161,12 @@ authdes_pk_create(char *servername, /* network name of server */ */ 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 */ @@ -239,13 +185,13 @@ authdes_pk_create(char *servername, /* network name of server */ 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); @@ -261,7 +207,8 @@ authdes_pk_create(char *servername, /* network name of server */ 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 { @@ -273,10 +220,10 @@ authdes_pk_create(char *servername, /* network name of server */ */ 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 */ @@ -293,13 +240,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 */ @@ -314,7 +262,6 @@ authdes_nextverf(AUTH *auth) { /* what the heck am I supposed to do??? */ } - /* @@ -323,14 +270,15 @@ authdes_nextverf(AUTH *auth) static bool_t authdes_marshal(AUTH *auth, XDR *xdrs) { +/* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; - des_block cryptbuf[2]; + des_block cryptbuf[2]; des_block ivec; int status; - long len; - int32_t *ixdr; + int len; + rpc_inline_t *ixdr; /* * Figure out the "time", accounting for any time difference @@ -339,30 +287,32 @@ authdes_marshal(AUTH *auth, XDR *xdrs) 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]; @@ -385,21 +335,21 @@ authdes_marshal(AUTH *auth, XDR *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); @@ -412,84 +362,90 @@ authdes_marshal(AUTH *auth, XDR *xdrs) static bool_t authdes_validate(AUTH *auth, struct opaque_auth *rverf) { +/* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_verf verf; int status; - u_long *ixdr; + 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) +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; @@ -505,38 +461,36 @@ authdes_refresh(AUTH *auth) static void authdes_destroy(AUTH *auth) { +/* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); FREE(ad->ad_servername, ad->ad_servernamelen + 1); + if (ad->ad_timehost) + FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); + if (ad->ad_netid) + FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); + if (ad->ad_uaddr) + FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); FREE(ad, sizeof(struct ad_private)); FREE(auth, sizeof(AUTH)); } - -#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(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); - } - 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; + + /* 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 db8930948f..8e02db4bda 100644 --- a/lib/libc/rpc/auth_none.c +++ b/lib/libc/rpc/auth_none.c @@ -28,7 +28,8 @@ * * @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro * @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.9 1999/08/28 00:00:32 peter Exp $ + * $NetBSD: auth_none.c,v 1.13 2000/01/22 22:19:17 mycroft Exp $ + * $FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.14 2006/02/27 22:10:58 deischen Exp $ * $DragonFly: src/lib/libc/rpc/auth_none.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -40,32 +41,33 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include "reentrant.h" +#include #include #include #include #include -#define MAX_MARSHEL_SIZE 20 +#include "un-namespace.h" +#include "mt_misc.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 *); + +static struct auth_ops *authnone_ops(void); static struct authnone_private { AUTH no_client; - char marshalled_client[MAX_MARSHEL_SIZE]; + char marshalled_client[MAX_MARSHAL_SIZE]; u_int mcnt; } *authnone_private; @@ -76,23 +78,27 @@ authnone_create(void) XDR xdr_stream; XDR *xdrs; + 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); xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); 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); } @@ -100,34 +106,66 @@ authnone_create(void) static bool_t authnone_marshal(AUTH *client, XDR *xdrs) { - struct authnone_private *ap = authnone_private; + struct authnone_private *ap; + bool_t dummy; - 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(void) +authnone_verf(AUTH *client) { } +/*ARGSUSED*/ static bool_t -authnone_validate(void) +authnone_validate(AUTH *client, struct opaque_auth *opaque) { return (TRUE); } +/*ARGSUSED*/ static bool_t -authnone_refresh(void) +authnone_refresh(AUTH *client, void *dummy) { return (FALSE); } +/*ARGSUSED*/ static void -authnone_destroy(void) +authnone_destroy(AUTH *client) +{ +} + +static struct auth_ops * +authnone_ops(void) { + static struct auth_ops ops; + +/* 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 e7281ae2c9..9463678a7c 100644 --- a/lib/libc/rpc/auth_time.c +++ b/lib/libc/rpc/auth_time.c @@ -1,5 +1,3 @@ -#pragma ident "@(#)auth_time.c 1.4 92/11/10 SMI" - /* * auth_time.c * @@ -26,12 +24,11 @@ * and returned. The SIGALRM processing is modified only if * needed to deal with TCP connections. * - * NOTE: This code has had the crap beaten out it in order to convert - * it from TI-RPC back to TD-RPC for use on FreeBSD. - * - * $FreeBSD: src/lib/libc/rpc/auth_time.c,v 1.4 2000/01/27 23:06:35 jasone Exp $ + * @(#)auth_time.c 1.4 92/11/10 SMI + * $FreeBSD: src/lib/libc/rpc/auth_time.c,v 1.12 2007/09/20 22:35:24 matteo Exp $ * $DragonFly: src/lib/libc/rpc/auth_time.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ + #include "namespace.h" #include #include @@ -46,19 +43,12 @@ #include #include #include +#include #undef NIS #include #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 +extern int _rpc_dtablesize(void); #ifdef TESTING #define msg(x) printf("ERROR: %s\n", x) @@ -157,6 +147,7 @@ get_server(struct sockaddr_in *sin, struct hostent *he; struct hostent dummy; char *ptr[2]; + endpoint *ep; if (host == NULL && sin == NULL) return (NULL); @@ -176,26 +167,34 @@ get_server(struct sockaddr_in *sin, * This is lame. We go around once for TCP, then again * for UDP. */ - for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); - i++, num_ep++) { + for (i = 0, ep = eps; (he->h_addr_list[i] != NULL) && (num_ep < maxep); + i++, ep++, num_ep++) { struct in_addr *a; a = (struct in_addr *)he->h_addr_list[i]; snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); - eps[num_ep].uaddr = strdup(hname); - eps[num_ep].family = strdup("inet"); - eps[num_ep].proto = strdup("tcp"); + ep->uaddr = strdup(hname); + ep->family = strdup("inet"); + ep->proto = strdup("tcp"); + if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) { + free_eps(eps, num_ep + 1); + return (NULL); + } } for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); - i++, num_ep++) { + i++, ep++, num_ep++) { struct in_addr *a; a = (struct in_addr *)he->h_addr_list[i]; snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); - eps[num_ep].uaddr = strdup(hname); - eps[num_ep].family = strdup("inet"); - eps[num_ep].proto = strdup("udp"); + ep->uaddr = strdup(hname); + ep->family = strdup("inet"); + ep->proto = strdup("udp"); + if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) { + free_eps(eps, num_ep + 1); + return (NULL); + } } srv->name = (nis_name) host; @@ -253,7 +252,8 @@ __rpc_get_time_offset(struct timeval *td, /* Time difference */ nis_server tsrv; void (*oldsig)() = NULL; /* old alarm handler */ struct sockaddr_in sin; - int s = RPC_ANYSOCK, len; + socklen_t len; + int s = RPC_ANYSOCK; int type = 0; td->tv_sec = 0; @@ -345,8 +345,8 @@ __rpc_get_time_offset(struct timeval *td, /* Time difference */ tv.tv_sec = 5; tv.tv_usec = 0; time_valid = 0; - status = clnt_call(clnt, RPCBPROC_GETTIME, xdr_void, NULL, - xdr_u_long, (char *)&thetime, tv); + status = clnt_call(clnt, RPCBPROC_GETTIME, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_u_long, &thetime, tv); /* * The only error we check for is anything but success. In * fact we could have seen PROGMISMATCH if talking to a 4.1 diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c index c8345e2c6f..b086331935 100644 --- a/lib/libc/rpc/auth_unix.c +++ b/lib/libc/rpc/auth_unix.c @@ -28,7 +28,8 @@ * * @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro * @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/auth_unix.c,v 1.12 1999/12/29 05:04:16 peter Exp $ + * $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/auth_unix.c,v 1.18 2007/06/14 20:07:35 harti Exp $ * $DragonFly: src/lib/libc/rpc/auth_unix.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -44,33 +45,32 @@ * */ +#include "namespace.h" +#include "reentrant.h" +#include + +#include +#include #include #include #include #include -#include #include #include #include #include - -/* - * 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 -}; +#include "un-namespace.h" +#include "mt_misc.h" + +/* auth_unix.c */ +static void authunix_destroy(AUTH *); +static bool_t authunix_marshal(AUTH *, XDR *); +static void authunix_nextverf(AUTH *); +static struct auth_ops *authunix_ops(void); +static bool_t authunix_refresh(AUTH *, void *); +static bool_t authunix_validate(AUTH *, struct opaque_auth *); +static void marshal_new_auth(AUTH *); /* * This struct is pointed to by the ah_private field of an auth_handle. @@ -84,21 +84,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. @@ -116,40 +101,36 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids) /* * Allocate and set up auth handle */ - auth = (AUTH *)mem_alloc(sizeof(*auth)); + au = NULL; + auth = mem_alloc(sizeof(*auth)); #ifndef _KERNEL if (auth == NULL) { - 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) { - 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 */ - gettimeofday(&now, (struct timezone *)0); + 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; /* @@ -164,11 +145,11 @@ authunix_create(char *machname, int uid, int gid, int len, int *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) { - 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. @@ -176,6 +157,17 @@ authunix_create(char *machname, int uid, int gid, int len, int *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 } /* @@ -186,31 +178,30 @@ AUTH * authunix_create_default(void) { int len; - char machname[MAX_MACHINE_NAME + 1]; - int uid; - int gid; - int gids[NGRPS]; - int i; - gid_t real_gids[NGROUPS]; - - if (gethostname(machname, MAX_MACHINE_NAME) == -1) + char machname[MAXHOSTNAMELEN + 1]; + uid_t uid; + gid_t gid; + gid_t gids[NGROUPS_MAX]; + + 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(NGROUPS_MAX, 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)); + if (len > NGRPS) + len = NGRPS; + /* 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) { @@ -220,20 +211,28 @@ authunix_nextverf(AUTH *auth) static bool_t authunix_marshal(AUTH *auth, XDR *xdrs) { - 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 *auth, struct opaque_auth verf) +authunix_validate(AUTH *auth, struct opaque_auth *verf) { 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, @@ -254,7 +253,7 @@ authunix_validate(AUTH *auth, struct opaque_auth verf) } static bool_t -authunix_refresh(AUTH *auth) +authunix_refresh(AUTH *auth, void *dummy) { struct audata *au = AUTH_PRIVATE(auth); struct authunix_parms aup; @@ -262,6 +261,8 @@ authunix_refresh(AUTH *auth) XDR xdrs; int stat; + assert(auth != NULL); + if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { /* there is no hope. Punt */ return (FALSE); @@ -270,7 +271,7 @@ authunix_refresh(AUTH *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); @@ -278,7 +279,7 @@ authunix_refresh(AUTH *auth) goto done; /* update the time and serialize in place */ - gettimeofday(&now, (struct timezone *)0); + gettimeofday(&now, NULL); aup.aup_time = now.tv_sec; xdrs.x_op = XDR_ENCODE; XDR_SETPOS(&xdrs, 0); @@ -298,8 +299,11 @@ done: static void authunix_destroy(AUTH *auth) { - 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) @@ -310,7 +314,7 @@ authunix_destroy(AUTH *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)); } /* @@ -320,16 +324,37 @@ authunix_destroy(AUTH *auth) static void marshal_new_auth(AUTH *auth) { - XDR xdr_stream; + XDR xdr_stream; XDR *xdrs = &xdr_stream; - struct audata *au = AUTH_PRIVATE(auth); + 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(void) +{ + static struct auth_ops ops; + + /* 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 b67a58931a..cd5e74521c 100644 --- a/lib/libc/rpc/authdes_prot.c +++ b/lib/libc/rpc/authdes_prot.c @@ -1,5 +1,3 @@ -/* @(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI */ -/* $DragonFly: src/lib/libc/rpc/authdes_prot.c,v 1.4 2008/10/28 17:23:45 swildner 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,37 +25,48 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * @(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SM; + * $FreeBSD: src/lib/libc/rpc/authdes_prot.c,v 1.5 2007/11/20 01:51:20 jb Exp $ + * $DragonFly: src/lib/libc/rpc/authdes_prot.c,v 1.4 2008/10/28 17:23:45 swildner Exp $ */ /* - * 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 #include #include #include +#include "un-namespace.h" #define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) bool_t xdr_authdes_cred(XDR *xdrs, struct authdes_cred *cred) { + enum authdes_namekind *padc_namekind = &cred->adc_namekind; /* * Unrolled xdr */ - ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind)); + ATTEMPT(xdr_enum(xdrs, (enum_t *) padc_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); @@ -71,7 +80,9 @@ xdr_authdes_verf(XDR *xdrs, struct authdes_verf *verf) /* * Unrolled xdr */ - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block))); - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u))); + 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 de95e4df22..b37c3e098f 100644 --- a/lib/libc/rpc/authunix_prot.c +++ b/lib/libc/rpc/authunix_prot.c @@ -28,7 +28,8 @@ * * @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro * @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/authunix_prot.c,v 1.6 1999/08/28 00:00:33 peter Exp $ + * $NetBSD: authunix_prot.c,v 1.12 2000/01/22 22:19:17 mycroft Exp $ + * $FreeBSD: src/lib/libc/rpc/authunix_prot.c,v 1.10 2007/11/20 01:51:20 jb Exp $ * $DragonFly: src/lib/libc/rpc/authunix_prot.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -39,11 +40,14 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include #include #include #include #include +#include "un-namespace.h" /* * XDR for unix authentication parameters. @@ -51,15 +55,20 @@ bool_t xdr_authunix_parms(XDR *xdrs, struct authunix_parms *p) { + int **paup_gids; + + assert(xdrs != NULL); + assert(p != NULL); + + paup_gids = &p->aup_gids; 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) ) { + && xdr_array(xdrs, (char **) paup_gids, + &(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 c266d8ae22..f79a6fe759 100644 --- a/lib/libc/rpc/bindresvport.3 +++ b/lib/libc/rpc/bindresvport.3 @@ -1,5 +1,6 @@ .\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI -.\" $FreeBSD: src/lib/libc/rpc/bindresvport.3,v 1.10.2.2 2001/12/14 18:33:56 ru Exp $ +.\" $NetBSD: bindresvport.3,v 1.8 2000/07/05 15:45:33 msaitoh Exp $ +.\" $FreeBSD: src/lib/libc/rpc/bindresvport.3,v 1.15 2002/12/18 12:45:10 ru Exp $ .\" $DragonFly: src/lib/libc/rpc/bindresvport.3,v 1.3 2007/08/18 20:48:47 swildner Exp $ .\" .Dd January 27, 2000 @@ -12,46 +13,64 @@ .Sh LIBRARY .Lb libc .Sh SYNOPSIS +.In sys/types.h .In rpc/rpc.h .Ft int .Fn bindresvport "int sd" "struct sockaddr_in *sin" .Ft int .Fn bindresvport_sa "int sd" "struct sockaddr *sa" .Sh DESCRIPTION +The .Fn bindresvport and .Fn bindresvport_sa +functions are used to bind a socket descriptor to a privileged .Tn IP port, that is, a port number in the range 0-1023. .Pp -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 is biased to .Dv AF_INET socket. +The .Fn bindresvport_sa +function acts exactly the same, with more neutral function prototype. Note that both functions behave exactly the same, and both support @@ -60,50 +79,26 @@ 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 +The +.Fn bindresvport +function +may also fail and set +.Va errno +for any of the errors specified for the calls +.Xr bind 2 , +.Xr getsockopt 2 , +or +.Xr setsockopt 2 . +.Sh SEE ALSO .Xr bind 2 , -.Xr 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 b83e283063..98de8e2efa 100644 --- a/lib/libc/rpc/bindresvport.c +++ b/lib/libc/rpc/bindresvport.c @@ -28,7 +28,8 @@ * * @(#)bindresvport.c 1.8 88/02/08 SMI * @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.12 2000/01/26 09:02:42 shin Exp $ + * $NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.16 2004/10/16 06:11:34 obrien Exp $ * $DragonFly: src/lib/libc/rpc/bindresvport.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -40,10 +41,16 @@ #include "namespace.h" #include -#include #include + #include + +#include +#include #include + +#include + #include #include "un-namespace.h" @@ -57,7 +64,7 @@ bindresvport(int sd, struct sockaddr_in *sin) } /* - * Bind a socket to a privileged port for whatever protocol. + * Bind a socket to a privileged IP port */ int bindresvport_sa(int sd, struct sockaddr *sa) @@ -65,10 +72,12 @@ bindresvport_sa(int sd, struct sockaddr *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); @@ -78,39 +87,44 @@ bindresvport_sa(int sd, struct sockaddr *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) return (error); - error = setsockopt(sd, proto, portrange, &portlow, + error = _setsockopt(sd, proto, portrange, &portlow, sizeof(portlow)); if (error < 0) return (error); @@ -118,10 +132,10 @@ bindresvport_sa(int sd, struct sockaddr *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; @@ -129,7 +143,7 @@ bindresvport_sa(int sd, struct sockaddr *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 0000000000..0701e1f6b6 --- /dev/null +++ b/lib/libc/rpc/clnt_bcast.c @@ -0,0 +1,668 @@ +/* + * 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 + * + * @(#)clnt_bcast.c 1.18 94/05/03 SMI; 1.15 89/04/21 Copyr 1988 Sun Micro + * $NetBSD: clnt_bcast.c,v 1.3 2000/07/06 03:05:20 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_bcast.c,v 1.9 2006/09/09 22:14:42 mbr Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include +#include +#include +#endif /* PORTMAP */ +#include +#include +#ifdef RPC_DEBUG +#include +#endif +#include +#include +#include +#include +#include +#include +#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_broadenable(int, int, struct broadif *); +void __rpc_freebroadifs(broadlist_t *); +int __rpc_getbroadifs(int, int, int, broadlist_t *); + +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) { + freeifaddrs(ifp); + return 0; + } + + for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { + if (ifap->ifa_addr->sa_family != af || + !(ifap->ifa_flags & IFF_UP)) + continue; + bip = (struct broadif *)malloc(sizeof *bip); + if (bip == NULL) + break; + bip->index = if_nametoindex(ifap->ifa_name); + if ( +#ifdef INET6 + af != AF_INET6 && +#endif + (ifap->ifa_flags & IFF_BROADCAST) && + ifap->ifa_broadaddr) { + memcpy(&bip->broadaddr, ifap->ifa_broadaddr, + (size_t)ifap->ifa_broadaddr->sa_len); + sin = (struct sockaddr_in *)(void *)&bip->broadaddr; + sin->sin_port = + ((struct sockaddr_in *) + (void *)res->ai_addr)->sin_port; + } else +#ifdef INET6 + if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) { + sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr; + inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr); + sin6->sin6_family = af; + sin6->sin6_len = sizeof *sin6; + sin6->sin6_port = + ((struct sockaddr_in6 *) + (void *)res->ai_addr)->sin6_port; + sin6->sin6_scope_id = bip->index; + } else +#endif + { + free(bip); + continue; + } + TAILQ_INSERT_TAIL(list, bip, link); + count++; + } + freeifaddrs(ifp); + freeaddrinfo(res); + + return count; +} + +void +__rpc_freebroadifs(broadlist_t *list) +{ + struct broadif *bip, *next; + + bip = TAILQ_FIRST(list); + + while (bip != NULL) { + next = TAILQ_NEXT(bip, link); + free(bip); + bip = next; + } +} + +int +/*ARGSUSED*/ +__rpc_broadenable(int af, int s, struct broadif *bip) +{ + int o = 1; + +#if 0 + if (af == AF_INET6) { + fprintf(stderr, "set v6 multicast if to %d\n", bip->index); + if (_setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index, + sizeof bip->index) < 0) + return -1; + } else +#endif + if (_setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 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; + struct netconfig *nconf; + int msec; + int pollretval; + int fds_found; + +#ifdef PORTMAP + size_t outlen_pmap = 0; + u_long port; /* Remote port number */ + int pmap_flag = 0; /* UDP exists ? */ + char *outbuf_pmap = NULL; + struct rmtcallargs barg_pmap; /* Remote arguments */ + struct rmtcallres bres_pmap; /* Remote results */ + u_int udpbufsz = 0; +#endif /* PORTMAP */ + + if (sys_auth == NULL) { + return (RPC_SYSTEMERROR); + } + /* + * initialization: create a fd, a broadcast address, and send the + * request on the broadcast transport. + * Listen on all of them and on replies, call the user supplied + * function. + */ + + if (nettype == NULL) + nettype = "datagram_n"; + if ((handle = __rpc_setconf(nettype)) == NULL) { + AUTH_DESTROY(sys_auth); + 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 */ + gettimeofday(&t, NULL); + msg.rm_xid = __RPC_GETXID(&t); + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = RPCBPROG; + msg.rm_call.cb_vers = RPCBVERS; + msg.rm_call.cb_proc = RPCBPROC_CALLIT; + barg.prog = prog; + barg.vers = vers; + barg.proc = proc; + barg.args.args_val = argsp; + barg.xdr_args = xargs; + bres.addr = uaddrp; + bres.results.results_val = resultsp; + bres.xdr_res = xresults; + msg.rm_call.cb_cred = sys_auth->ah_cred; + msg.rm_call.cb_verf = sys_auth->ah_verf; + xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); + if ((!xdr_callmsg(xdrs, &msg)) || + (!xdr_rpcb_rmtcallargs(xdrs, + (struct rpcb_rmtcallargs *)(void *)&barg))) { + stat = RPC_CANTENCODEARGS; + goto done_broad; + } + outlen = xdr_getpos(xdrs); + xdr_destroy(xdrs); + +#ifdef PORTMAP + /* Prepare the packet for version 2 PORTMAP */ + if (pmap_flag) { + msg.rm_xid++; /* One way to distinguish */ + msg.rm_call.cb_prog = PMAPPROG; + msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_proc = PMAPPROC_CALLIT; + barg_pmap.prog = prog; + barg_pmap.vers = vers; + barg_pmap.proc = proc; + barg_pmap.args_ptr = argsp; + barg_pmap.xdr_args = xargs; + bres_pmap.port_ptr = &port; + bres_pmap.xdr_results = xresults; + bres_pmap.results_ptr = resultsp; + xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); + if ((! xdr_callmsg(xdrs, &msg)) || + (! xdr_rmtcall_args(xdrs, &barg_pmap))) { + stat = RPC_CANTENCODEARGS; + goto done_broad; + } + outlen_pmap = xdr_getpos(xdrs); + xdr_destroy(xdrs); + } +#endif /* PORTMAP */ + + /* + * Basic loop: broadcast the packets to transports which + * support data packets of size such that one can encode + * all the arguments. + * Wait a while for response(s). + * The response timeout grows larger per iteration. + */ + for (msec = inittime; msec <= waittime; msec += msec) { + struct broadif *bip; + + /* Broadcast all the packets now */ + for (i = 0; i < fdlistno; i++) { + if (fdlist[i].dsize < outlen) { + stat = RPC_CANTSEND; + continue; + } + for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL; + bip = TAILQ_NEXT(bip, link)) { + void *addr; + + addr = &bip->broadaddr; + + __rpc_broadenable(fdlist[i].af, fdlist[i].fd, + bip); + + /* + * Only use version 3 if lowvers is not set + */ + + if (!__rpc_lowvers) + if (_sendto(fdlist[i].fd, outbuf, + outlen, 0, (struct sockaddr*)addr, + (size_t)fdlist[i].asize) != + outlen) { +#ifdef RPC_DEBUG + perror("sendto"); +#endif + warnx("clnt_bcast: cannot send" + "broadcast packet"); + stat = RPC_CANTSEND; + continue; + }; +#ifdef RPC_DEBUG + if (!__rpc_lowvers) + fprintf(stderr, "Broadcast packet sent " + "for %s\n", + fdlist[i].nconf->nc_netid); +#endif +#ifdef PORTMAP + /* + * Send the version 2 packet also + * for UDP/IP + */ + if (pmap_flag && + fdlist[i].proto == IPPROTO_UDP) { + if (_sendto(fdlist[i].fd, outbuf_pmap, + outlen_pmap, 0, addr, + (size_t)fdlist[i].asize) != + outlen_pmap) { + warnx("clnt_bcast: " + "Cannot send broadcast packet"); + stat = RPC_CANTSEND; + continue; + } + } +#ifdef RPC_DEBUG + fprintf(stderr, "PMAP Broadcast packet " + "sent for %s\n", + fdlist[i].nconf->nc_netid); +#endif +#endif /* PORTMAP */ + } + /* End for sending all packets on this transport */ + } /* End for sending on all transports */ + + if (eachresult == NULL) { + stat = RPC_SUCCESS; + goto done_broad; + } + + /* + * Get all the replies from these broadcast requests + */ + recv_again: + + switch (pollretval = _poll(pfd, fdlistno, msec)) { + case 0: /* timed out */ + stat = RPC_TIMEDOUT; + continue; + case -1: /* some kind of error - we ignore it */ + goto recv_again; + } /* end of poll results switch */ + + for (i = fds_found = 0; + i < fdlistno && fds_found < pollretval; i++) { + bool_t done = FALSE; + + if (pfd[i].revents == 0) + continue; + else if (pfd[i].revents & POLLNVAL) { + /* + * Something bad has happened to this descri- + * ptor. We can cause _poll() to ignore + * it simply by using a negative fd. We do that + * rather than compacting the pfd[] and fdlist[] + * arrays. + */ + pfd[i].fd = -1; + fds_found++; + continue; + } else + fds_found++; +#ifdef RPC_DEBUG + fprintf(stderr, "response for %s\n", + fdlist[i].nconf->nc_netid); +#endif + try_again: + inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, + 0, (struct sockaddr *)(void *)&fdlist[i].raddr, + &fdlist[i].asize); + if (inlen < 0) { + if (errno == EINTR) + goto try_again; + warnx("clnt_bcast: Cannot receive reply to " + "broadcast"); + stat = RPC_CANTRECV; + continue; + } + if (inlen < sizeof (u_int32_t)) + continue; /* Drop that and go ahead */ + /* + * see if reply transaction id matches sent id. + * If so, decode the results. If return id is xid + 1 + * it was a PORTMAP reply + */ + if (*((u_int32_t *)(void *)(inbuf)) == + *((u_int32_t *)(void *)(outbuf))) { + pmap_reply_flag = 0; + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = + (caddr_t)(void *)&bres; + msg.acpted_rply.ar_results.proc = + (xdrproc_t)xdr_rpcb_rmtcallres; +#ifdef PORTMAP + } else if (pmap_flag && + *((u_int32_t *)(void *)(inbuf)) == + *((u_int32_t *)(void *)(outbuf_pmap))) { + pmap_reply_flag = 1; + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = + (caddr_t)(void *)&bres_pmap; + msg.acpted_rply.ar_results.proc = + (xdrproc_t)xdr_rmtcallres; +#endif /* PORTMAP */ + } else + continue; + xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); + if (xdr_replymsg(xdrs, &msg)) { + if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) { + struct netbuf 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; + xdr_replymsg(xdrs, &msg); + (*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) + free(inbuf); + if (outbuf) + free(outbuf); +#ifdef PORTMAP + if (outbuf_pmap) + free(outbuf_pmap); +#endif /* PORTMAP */ + for (i = 0; i < fdlistno; i++) { + _close(fdlist[i].fd); + __rpc_freebroadifs(&fdlist[i].nal); + } + AUTH_DESTROY(sys_auth); + __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 0000000000..3fd389348a --- /dev/null +++ b/lib/libc/rpc/clnt_dg.c @@ -0,0 +1,768 @@ +/* + * 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 + * + * @(#)clnt_dg.c 1.23 94/04/22 SMI; 1.19 89/03/16 Copyr 1988 Sun Micro + * $NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_dg.c,v 1.18 2006/02/27 22:10:58 deischen Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * Implements a connectionless client side RPC. + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" +#include "rpc_com.h" +#include "mt_misc.h" + + +#define RPC_MAX_BACKOFF 30 /* seconds */ + + +static void clnt_dg_abort(CLIENT *); +static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *, + xdrproc_t, void *, struct timeval); +static bool_t clnt_dg_control(CLIENT *, u_int, void *); +static void clnt_dg_destroy(CLIENT *); +static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *); +static void clnt_dg_geterr(CLIENT *, struct rpc_err *); +static struct clnt_ops *clnt_dg_ops(void); +static bool_t time_not_ok(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; +static cond_t *dg_cv; +#define release_fd_lock(fd, mask) { \ + mutex_lock(&clnt_fd_lock); \ + dg_fd_locks[fd] = 0; \ + mutex_unlock(&clnt_fd_lock); \ + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \ + cond_signal(&dg_cv[fd]); \ +} + +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 */ + int cu_async; + int cu_connect; /* Use connect(). */ + int cu_connected; /* Have done connect(). */ + struct kevent cu_kin; + int cu_kq; + 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(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; + memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len); + cu->cu_rlen = svcaddr->len; + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; + /* Other values can also be set through clnt_control() */ + cu->cu_wait.tv_sec = 15; /* heuristically chosen */ + cu->cu_wait.tv_usec = 0; + cu->cu_total.tv_sec = -1; + cu->cu_total.tv_usec = -1; + cu->cu_sendsz = sendsz; + cu->cu_recvsz = recvsz; + cu->cu_async = FALSE; + cu->cu_connect = FALSE; + cu->cu_connected = FALSE; + 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 + 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->cu_kq = -1; + EV_SET(&cu->cu_kin, cu->cu_fd, EVFILT_READ, EV_ADD, 0, 0, 0); + 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(CLIENT *cl, /* client handle */ + rpcproc_t proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + void *argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + void *resultsp, /* pointer to results */ + struct timeval utimeout) /* seconds to wait before giving up */ +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + XDR *xdrs; + size_t outlen = 0; + struct rpc_msg reply_msg; + XDR reply_xdrs; + bool_t ok; + int nrefreshes = 2; /* number of times to refresh cred */ + struct timeval timeout; + struct timeval retransmit_time; + struct timeval next_sendtime, starttime, time_waited, tv; + struct timespec ts; + struct kevent kv; + struct sockaddr *sa; + sigset_t mask; + sigset_t newmask; + socklen_t inlen, salen; + ssize_t recvlen = 0; + int kin_len, n, rpc_lock_value; + u_int32_t xid; + + outlen = 0; + 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 */ + } + + if (cu->cu_connect && !cu->cu_connected) { + if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr, + cu->cu_rlen) < 0) { + cu->cu_error.re_errno = errno; + cu->cu_error.re_status = RPC_CANTSEND; + goto out; + } + cu->cu_connected = 1; + } + if (cu->cu_connected) { + sa = NULL; + salen = 0; + } else { + sa = (struct sockaddr *)&cu->cu_raddr; + salen = cu->cu_rlen; + } + time_waited.tv_sec = 0; + time_waited.tv_usec = 0; + retransmit_time = next_sendtime = cu->cu_wait; + gettimeofday(&starttime, NULL); + + /* Clean up in case the last call ended in a longjmp(3) call. */ + if (cu->cu_kq >= 0) + _close(cu->cu_kq); + if ((cu->cu_kq = kqueue()) < 0) { + cu->cu_error.re_errno = errno; + cu->cu_error.re_status = RPC_CANTSEND; + goto out; + } + kin_len = 1; + +call_again: + xdrs = &(cu->cu_outxdrs); + if (cu->cu_async == TRUE && xargs == NULL) + goto get_reply; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, cu->cu_xdrpos); + /* + * the transaction is the first thing in the out buffer + * XXX Yes, and it's in network byte order, so we should to + * be careful when we increment it, shouldn't we. + */ + xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf)); + xid++; + *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid); + + if ((! XDR_PUTINT32(xdrs, &proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) { + cu->cu_error.re_status = RPC_CANTENCODEARGS; + goto out; + } + outlen = (size_t)XDR_GETPOS(xdrs); + +send_again: + if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) { + cu->cu_error.re_errno = errno; + cu->cu_error.re_status = RPC_CANTSEND; + goto out; + } + + /* + * Hack to provide rpc-based message passing + */ + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { + cu->cu_error.re_status = RPC_TIMEDOUT; + goto out; + } + +get_reply: + + /* + * sub-optimal code appears here because we have + * some clock time to spare while the packets are in flight. + * (We assume that this is actually only executed once.) + */ + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + + for (;;) { + /* Decide how long to wait. */ + if (timercmp(&next_sendtime, &timeout, <)) + timersub(&next_sendtime, &time_waited, &tv); + else + timersub(&timeout, &time_waited, &tv); + if (tv.tv_sec < 0 || tv.tv_usec < 0) + tv.tv_sec = tv.tv_usec = 0; + TIMEVAL_TO_TIMESPEC(&tv, &ts); + + n = _kevent(cu->cu_kq, &cu->cu_kin, kin_len, &kv, 1, &ts); + /* We don't need to register the event again. */ + kin_len = 0; + + if (n == 1) { + if (kv.flags & EV_ERROR) { + cu->cu_error.re_errno = kv.data; + cu->cu_error.re_status = RPC_CANTRECV; + goto out; + } + /* We have some data now */ + do { + recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf, + cu->cu_recvsz, 0, NULL, NULL); + } while (recvlen < 0 && errno == EINTR); + if (recvlen < 0 && errno != EWOULDBLOCK) { + cu->cu_error.re_errno = errno; + cu->cu_error.re_status = RPC_CANTRECV; + goto out; + } + if (recvlen >= sizeof(u_int32_t) && + (cu->cu_async == TRUE || + *((u_int32_t *)(void *)(cu->cu_inbuf)) == + *((u_int32_t *)(void *)(cu->cu_outbuf)))) { + /* We now assume we have the proper reply. */ + break; + } + } + if (n == -1 && errno != EINTR) { + cu->cu_error.re_errno = errno; + cu->cu_error.re_status = RPC_CANTRECV; + goto out; + } + gettimeofday(&tv, NULL); + timersub(&tv, &starttime, &time_waited); + + /* Check for timeout. */ + if (timercmp(&time_waited, &timeout, >)) { + cu->cu_error.re_status = RPC_TIMEDOUT; + goto out; + } + + /* Retransmit if necessary. */ + if (timercmp(&time_waited, &next_sendtime, >)) { + /* update retransmit_time */ + if (retransmit_time.tv_sec < RPC_MAX_BACKOFF) + timeradd(&retransmit_time, &retransmit_time, + &retransmit_time); + timeradd(&next_sendtime, &retransmit_time, + &next_sendtime); + goto send_again; + } + } + inlen = (socklen_t)recvlen; + + /* + * now decode and validate the response + */ + + xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE); + ok = xdr_replymsg(&reply_xdrs, &reply_msg); + /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ + if (ok) { + if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (reply_msg.acpted_rply.ar_stat == SUCCESS)) + cu->cu_error.re_status = RPC_SUCCESS; + else + _seterr_reply(&reply_msg, &(cu->cu_error)); + + if (cu->cu_error.re_status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(cl->cl_auth, + &reply_msg.acpted_rply.ar_verf)) { + cu->cu_error.re_status = RPC_AUTHERROR; + cu->cu_error.re_why = AUTH_INVALIDRESP; + } + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { + xdrs->x_op = XDR_FREE; + xdr_opaque_auth(xdrs, + &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + /* + * If unsuccesful AND error is an authentication error + * then refresh credentials and try again, else break + */ + else if (cu->cu_error.re_status == RPC_AUTHERROR) + /* maybe our credentials need to be refreshed ... */ + if (nrefreshes > 0 && + AUTH_REFRESH(cl->cl_auth, &reply_msg)) { + nrefreshes--; + goto call_again; + } + /* end of unsuccessful completion */ + } /* end of valid reply message */ + else { + cu->cu_error.re_status = RPC_CANTDECODERES; + + } +out: + if (cu->cu_kq >= 0) + _close(cu->cu_kq); + cu->cu_kq = -1; + release_fd_lock(cu->cu_fd, mask); + return (cu->cu_error.re_status); +} + +static void +clnt_dg_geterr(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(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + XDR *xdrs = &(cu->cu_outxdrs); + bool_t dummy; + 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(CLIENT *h) +{ +} + +static bool_t +clnt_dg_control(CLIENT *cl, u_int request, void *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 *)info)) { + release_fd_lock(cu->cu_fd, mask); + return (FALSE); + } + cu->cu_total = *(struct timeval *)info; + break; + case CLGET_TIMEOUT: + *(struct timeval *)info = cu->cu_total; + break; + case CLGET_SERVER_ADDR: /* Give him the fd address */ + /* Now obsolete. Only for backward compatibility */ + memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen); + break; + case CLSET_RETRY_TIMEOUT: + if (time_not_ok((struct timeval *)info)) { + release_fd_lock(cu->cu_fd, mask); + return (FALSE); + } + cu->cu_wait = *(struct timeval *)info; + break; + case CLGET_RETRY_TIMEOUT: + *(struct timeval *)info = cu->cu_wait; + break; + case CLGET_FD: + *(int *)info = cu->cu_fd; + break; + case CLGET_SVC_ADDR: + addr = (struct netbuf *)info; + addr->buf = &cu->cu_raddr; + addr->len = cu->cu_rlen; + addr->maxlen = sizeof cu->cu_raddr; + break; + case CLSET_SVC_ADDR: /* set to new address */ + addr = (struct netbuf *)info; + if (addr->len < sizeof cu->cu_raddr) { + release_fd_lock(cu->cu_fd, mask); + return (FALSE); + } + memcpy(&cu->cu_raddr, addr->buf, addr->len); + cu->cu_rlen = addr->len; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_int32_t *)info = + ntohl(*(u_int32_t *)(void *)cu->cu_outbuf); + break; + + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_int32_t *)(void *)cu->cu_outbuf = + htonl(*(u_int32_t *)info - 1); + /* decrement by 1 as clnt_dg_call() increments once */ + break; + + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_int32_t *)info = + ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf + + 4 * BYTES_PER_XDR_UNIT)); + break; + + case CLSET_VERS: + *(u_int32_t *)(void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_int32_t *)info); + break; + + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the fourth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_int32_t *)info = + ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf + + 3 * BYTES_PER_XDR_UNIT)); + break; + + case CLSET_PROG: + *(u_int32_t *)(void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_int32_t *)info); + break; + case CLSET_ASYNC: + cu->cu_async = *(int *)info; + break; + case CLSET_CONNECT: + cu->cu_connect = *(int *)info; + break; + default: + release_fd_lock(cu->cu_fd, mask); + return (FALSE); + } + release_fd_lock(cu->cu_fd, mask); + return (TRUE); +} + +static void +clnt_dg_destroy(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) + _close(cu_fd); + if (cu->cu_kq >= 0) + _close(cu->cu_kq); + 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(void) +{ + static struct clnt_ops ops; + 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(struct timeval *t) +{ + return (t->tv_sec < -1 || t->tv_sec > 100000000 || + t->tv_usec < -1 || t->tv_usec > 1000000); +} diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c index 316ca9c5a9..3b8dc20aa2 100644 --- a/lib/libc/rpc/clnt_generic.c +++ b/lib/libc/rpc/clnt_generic.c @@ -1,4 +1,21 @@ /* + * The contents of this file are subject to the Sun Standards + * License Version 1.0 the (the "License";) You may not use + * this file except in compliance with the License. You may + * obtain a copy of the License at lib/libc/rpc/LICENSE + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is Copyright 1998 by Sun Microsystems, Inc + * + * The Initial Developer of the Original Code is: Sun + * Microsystems, Inc. + * + * All Rights Reserved. + * * 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 @@ -28,105 +45,417 @@ * * @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI * @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_generic.c,v 1.9.2.1 2001/03/05 10:48:28 obrien Exp $ + * @(#)clnt_generic.c 1.40 99/04/21 SMI + * $NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_generic.c,v 1.15 2004/10/16 06:11:34 obrien Exp $ * $DragonFly: src/lib/libc/rpc/clnt_generic.c,v 1.4 2005/01/31 22:29:38 dillon Exp $ */ /* - * Copyright (C) 1987, Sun Microsystems, Inc. + * Copyright (c) 1986-1996,1998 by Sun Microsystems, Inc. + * All rights reserved. */ -#include +#include "namespace.h" +#include "reentrant.h" +#include +#include #include +#include +#include +#include #include #include +#include +#include +#include #include +#include +#include +#include "un-namespace.h" +#include "rpc_com.h" + +extern bool_t __rpc_is_local_host(const char *); +int __rpc_raise_fd(int); + +#ifndef NETIDLEN +#define NETIDLEN 32 +#endif + /* - * Generic client creation: takes (hostname, program-number, protocol) and + * Generic client creation with version checking the value of + * vers_out is set to the highest server supported value + * vers_low <= vers_out <= vers_high AND an error results + * if this can not be done. + * + * It calls clnt_create_vers_timed() with a NULL value for the timeout + * pointer, which indicates that the default timeout should be used. + */ +CLIENT * +clnt_create_vers(const char *hostname, rpcprog_t prog, rpcvers_t *vers_out, + rpcvers_t vers_low, rpcvers_t vers_high, const char *nettype) +{ + + return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low, + vers_high, nettype, NULL)); +} + +/* + * This the routine has the same definition as clnt_create_vers(), + * except it takes an additional timeout parameter - a pointer to + * a timeval structure. A NULL value for the pointer indicates + * that the default timeout value should be used. + */ +CLIENT * +clnt_create_vers_timed(const char *hostname, rpcprog_t prog, + rpcvers_t *vers_out, rpcvers_t vers_low, rpcvers_t vers_high, + const char *nettype, const struct timeval *tp) +{ + CLIENT *clnt; + struct timeval to; + enum clnt_stat rpc_stat; + struct rpc_err rpcerr; + + clnt = clnt_create_timed(hostname, prog, vers_high, nettype, tp); + if (clnt == NULL) { + return (NULL); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void, + (char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, to); + if (rpc_stat == RPC_SUCCESS) { + *vers_out = vers_high; + return (clnt); + } + while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) { + unsigned int minvers, maxvers; + + clnt_geterr(clnt, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + if (maxvers < vers_high) + vers_high = maxvers; + else + vers_high--; + if (minvers > vers_low) + vers_low = minvers; + if (vers_low > vers_high) { + goto error; + } + CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high); + rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void, + (char *)NULL, (xdrproc_t)xdr_void, + (char *)NULL, to); + if (rpc_stat == RPC_SUCCESS) { + *vers_out = vers_high; + return (clnt); + } + } + clnt_geterr(clnt, &rpcerr); + +error: + rpc_createerr.cf_stat = rpc_stat; + rpc_createerr.cf_error = rpcerr; + clnt_destroy(clnt); + return (NULL); +} + +/* + * Top level client creation routine. + * Generic client creation: takes (servers name, program-number, nettype) and * returns client handle. Default options are set, which the user can * change using the rpc equivalent of _ioctl()'s. + * + * It tries for all the netids in that particular class of netid until + * it succeeds. + * XXX The error message in the case of failure will be the one + * pertaining to the last create error. + * + * It calls clnt_create_timed() with the default timeout. */ CLIENT * -clnt_create(const char *hostname, u_long prog, u_long vers, const char *proto) +clnt_create(const char *hostname, rpcprog_t prog, rpcvers_t vers, + const char *nettype) { - 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); - } - - h = gethostbyname(hostname); - if (h == NULL) { - rpc_createerr.cf_stat = RPC_UNKNOWNHOST; - return (NULL); + + return (clnt_create_timed(hostname, prog, vers, nettype, NULL)); +} + +/* + * This the routine has the same definition as clnt_create(), + * except it takes an additional timeout parameter - a pointer to + * a timeval structure. A NULL value for the pointer indicates + * that the default timeout value should be used. + * + * This function calls clnt_tp_create_timed(). + */ +CLIENT * +clnt_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers, + const char *netclass, const struct timeval *tp) +{ + struct netconfig *nconf; + CLIENT *clnt = NULL; + void *handle; + enum clnt_stat save_cf_stat = RPC_SUCCESS; + struct rpc_err save_cf_error; + char nettype_array[NETIDLEN]; + char *nettype = &nettype_array[0]; + + if (netclass == NULL) + nettype = NULL; + else { + size_t len = strlen(netclass); + if (len >= sizeof (nettype_array)) { + rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; + return (NULL); + } + strcpy(nettype, netclass); } - if (h->h_addrtype != AF_INET) { - /* - * Only support INET for now - */ - rpc_createerr.cf_stat = RPC_SYSTEMERROR; - rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; + + if ((handle = __rpc_setconf((char *)nettype)) == NULL) { + rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } - 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_createerr.cf_stat = RPC_SUCCESS; + while (clnt == NULL) { + if ((nconf = __rpc_getconf(handle)) == NULL) { + if (rpc_createerr.cf_stat == RPC_SUCCESS) + rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; + break; + } +#ifdef CLNT_DEBUG + printf("trying netid %s\n", nconf->nc_netid); +#endif + clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp); + if (clnt) + break; + else + /* + * Since we didn't get a name-to-address + * translation failure here, we remember + * this particular error. The object of + * this is to enable us to return to the + * caller a more-specific error than the + * unhelpful ``Name to address translation + * failed'' which might well occur if we + * merely returned the last error (because + * the local loopbacks are typically the + * last ones in /etc/netconfig and the most + * likely to be unable to translate a host + * name). We also check for a more + * meaningful error than ``unknown host + * name'' for the same reasons. + */ + if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE && + rpc_createerr.cf_stat != RPC_UNKNOWNHOST) { + save_cf_stat = rpc_createerr.cf_stat; + save_cf_error = rpc_createerr.cf_error; + } + } + + /* + * Attempt to return an error more specific than ``Name to address + * translation failed'' or ``unknown host name'' + */ + if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE || + rpc_createerr.cf_stat == RPC_UNKNOWNHOST) && + (save_cf_stat != RPC_SUCCESS)) { + rpc_createerr.cf_stat = save_cf_stat; + rpc_createerr.cf_error = save_cf_error; + } + __rpc_endconf(handle); + return (clnt); +} + +/* + * Generic client creation: takes (servers name, program-number, netconf) and + * returns client handle. Default options are set, which the user can + * change using the rpc equivalent of _ioctl()'s : clnt_control() + * It finds out the server address from rpcbind and calls clnt_tli_create(). + * + * It calls clnt_tp_create_timed() with the default timeout. + */ +CLIENT * +clnt_tp_create(const char *hostname, rpcprog_t prog, rpcvers_t vers, + const struct netconfig *nconf) +{ + + return (clnt_tp_create_timed(hostname, prog, vers, nconf, NULL)); +} + +/* + * This has the same definition as clnt_tp_create(), except it + * takes an additional parameter - a pointer to a timeval structure. + * A NULL value for the timeout pointer indicates that the default + * value for the timeout should be used. + */ +CLIENT * +clnt_tp_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers, + const struct netconfig *nconf, const struct timeval *tp) +{ + struct netbuf *svcaddr; /* servers address */ + CLIENT *cl = NULL; /* client handle */ + + if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; - 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) { + + /* + * Get the address of the server + */ + if ((svcaddr = __rpcb_findaddr_timed(prog, vers, + (struct netconfig *)nconf, (char *)hostname, + &cl, (struct timeval *)tp)) == NULL) { + /* appropriate error number is set by rpcbind libraries */ + return (NULL); + } + if (cl == NULL) { + cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr, + prog, vers, 0, 0); + } 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); + CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog); + CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers); + } else { + CLNT_DESTROY(cl); + cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr, + prog, vers, 0, 0); + } + } + 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(int fd, const struct netconfig *nconf, + struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers, + uint sendsz, uint recvsz) +{ + CLIENT *cl; /* client handle */ + bool_t madefd = FALSE; /* whether fd opened here */ + long servtype; + int one = 1; + struct __rpc_sockinfo si; + extern int __rpc_minfd; + + 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 - break; - case IPPROTO_TCP: - client = clnttcp_create(&sin, prog, vers, &sock, 0, 0); - if (client == NULL) { + + fd = __rpc_nconf2fd(nconf); + + if (fd == -1) + goto err; + if (fd < __rpc_minfd) + fd = __rpc_raise_fd(fd); + 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 0 /* XXX do we need this? */ - tv.tv_sec = 25; - tv.tv_usec = 0; - clnt_control(client, CLSET_TIMEOUT, &tv); -#endif + } + + if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) { + rpc_createerr.cf_stat = RPC_UNKNOWNHOST; /* XXX */ + goto err1; + } + + switch (servtype) { + case NC_TPI_COTS: + cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz); + break; + case NC_TPI_COTS_ORD: + if (nconf && ((strcmp(nconf->nc_protofmly, "inet") == 0))) { + _setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, + sizeof (one)); + } + cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz); + 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; + } + + 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) { + CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); +/* CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */ + }; + + return (cl); + +err: + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; +err1: if (madefd) + _close(fd); + return (NULL); +} + +/* + * To avoid conflicts with the "magic" file descriptors (0, 1, and 2), + * we try to not use them. The __rpc_raise_fd() routine will dup + * a descriptor to a higher value. If we fail to do it, we continue + * to use the old one (and hope for the best). + */ +int __rpc_minfd = 3; + +int +__rpc_raise_fd(int fd) +{ + int nfd; + + if (fd >= __rpc_minfd) + return (fd); + + if ((nfd = _fcntl(fd, F_DUPFD, __rpc_minfd)) == -1) + return (fd); + + if (_fsync(nfd) == -1) { + _close(nfd); + return (fd); } - return (client); + + if (_close(fd) == -1) { + /* this is okay, we will syslog an error, then use the new fd */ + syslog(LOG_ERR, "could not close() fd %d; mem & fd leak", fd); + } + + return (nfd); } diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c index 91dddb73c2..46e6a85d81 100644 --- a/lib/libc/rpc/clnt_perror.c +++ b/lib/libc/rpc/clnt_perror.c @@ -28,7 +28,8 @@ * * @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro * @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_perror.c,v 1.11.2.1 2000/08/23 00:02:04 jhb Exp $ + * $NetBSD: clnt_perror.c,v 1.24 2000/06/02 23:11:07 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_perror.c,v 1.17 2004/10/16 06:11:34 obrien Exp $ * $DragonFly: src/lib/libc/rpc/clnt_perror.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ @@ -38,19 +39,24 @@ * Copyright (C) 1984, Sun Microsystems, Inc. * */ +#include "namespace.h" +#include #include #include #include + #include #include #include #include - -static char *auth_errmsg(); -#define CLNT_PERROR_BUFLEN 256 +#include "un-namespace.h" static char *buf; +static char *_buf(void); +static char *auth_errmsg(enum auth_stat); +#define CLNT_PERROR_BUFLEN 256 + static char * _buf(void) { @@ -68,15 +74,29 @@ clnt_sperror(CLIENT *rpch, 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); - snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s", s, clnt_sperrno(e.re_status)); - str += strlen(str); + if ((i = snprintf(str, len, "%s: ", s)) > 0) { + str += i; + len -= i; + } + + strncpy(str, clnt_sperrno(e.re_status), len - 1); + i = strlen(str); + str += i; + len -= i; switch (e.re_status) { case RPC_SUCCESS: @@ -96,54 +116,73 @@ clnt_sperror(CLIENT *rpch, const char *s) case RPC_CANTSEND: case RPC_CANTRECV: - snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart), - "; errno = %s\n", strerror(e.re_errno)); + i = snprintf(str, len, "; errno = %s", strerror(e.re_errno)); + if (i > 0) { + str += i; + len -= i; + } break; case RPC_VERSMISMATCH: - 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); + if (i > 0) { + str += i; + len -= i; + } break; case RPC_AUTHERROR: err = auth_errmsg(e.re_why); - sprintf(str,"; why = "); - str += strlen(str); + i = snprintf(str, len, "; why = "); + if (i > 0) { + str += i; + len -= i; + } if (err != NULL) { - sprintf(str, "%s\n",err); + i = snprintf(str, len, "%s",err); } else { - sprintf(str, - "(unknown authentication error - %d)\n", + i = snprintf(str, len, + "(unknown authentication error - %d)", (int) e.re_why); } + if (i > 0) { + str += i; + len -= i; + } break; case RPC_PROGVERSMISMATCH: - 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); + if (i > 0) { + str += i; + len -= i; + } break; default: /* unknown */ - 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); + if (i > 0) { + str += i; + len -= i; + } break; } - if (strstart[CLNT_PERROR_BUFLEN-2] != '\0') { - strstart[CLNT_PERROR_BUFLEN-2] = '\n'; - strstart[CLNT_PERROR_BUFLEN-1] = '\0'; - } + strstart[CLNT_PERROR_BUFLEN-1] = '\0'; return(strstart) ; } void clnt_perror(CLIENT *rpch, const char *s) { - fprintf(stderr,"%s\n",clnt_sperror(rpch,s)); -} + assert(rpch != NULL); + assert(s != NULL); + + fprintf(stderr, "%s\n", clnt_sperror(rpch,s)); +} static const char *const rpc_errlist[] = { "RPC: Success", /* 0 - RPC_SUCCESS */ @@ -176,6 +215,7 @@ clnt_sperrno(enum clnt_stat stat) unsigned int errnum = stat; if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) + /* LINTED interface problem */ return (char *)rpc_errlist[errnum]; return ("RPC: (unknown error code)"); @@ -184,35 +224,58 @@ clnt_sperrno(enum clnt_stat stat) void clnt_perrno(enum clnt_stat num) { - fprintf(stderr,"%s\n",clnt_sperrno(num)); + fprintf(stderr, "%s\n", clnt_sperrno(num)); } char * clnt_spcreateerror(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); + if (i > 0) + len -= i; + strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1); switch (rpc_createerr.cf_stat) { case RPC_PMAPFAILURE: - snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, - clnt_sperrno(rpc_createerr.cf_stat), - clnt_sperrno(rpc_createerr.cf_error.re_status)); + strncat(str, " - ", len - 1); + strncat(str, + clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4); break; case RPC_SYSTEMERROR: - snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, - clnt_sperrno(rpc_createerr.cf_stat), - strerror(rpc_createerr.cf_error.re_errno)); + strncat(str, " - ", len - 1); + 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: - 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); } @@ -220,15 +283,18 @@ clnt_spcreateerror(const char *s) void clnt_pcreateerror(const char *s) { - fprintf(stderr,"%s\n",clnt_spcreateerror(s)); + + assert(s != NULL); + + 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 */ @@ -240,6 +306,7 @@ auth_errmsg(enum auth_stat stat) unsigned int errnum = stat; if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0]))) + /* LINTED interface problem */ return (char *)auth_errlist[errnum]; return(NULL); diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c index 6d0a86e92c..b797e3279d 100644 --- a/lib/libc/rpc/clnt_raw.c +++ b/lib/libc/rpc/clnt_raw.c @@ -28,7 +28,8 @@ * * @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro * @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_raw.c,v 1.10 1999/08/28 00:00:36 peter Exp $ + * $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_raw.c,v 1.20 2006/02/27 22:10:58 deischen Exp $ * $DragonFly: src/lib/libc/rpc/clnt_raw.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -40,12 +41,20 @@ * Memory based rpc for simple testing and timing. * Interface to create an rpc client and server in the same process. * This lets us similate rpc and get round trip overhead, without - * any interference from the kernal. + * any interference from the kernel. */ -#include -#include +#include "namespace.h" +#include "reentrant.h" +#include +#include #include +#include + +#include +#include +#include "un-namespace.h" +#include "mt_misc.h" #define MCALL_MSG_SIZE 24 @@ -55,44 +64,45 @@ 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 void clnt_raw_abort(CLIENT *); +static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *, + xdrproc_t, void *, struct timeval); +static bool_t clnt_raw_control(CLIENT *, u_int, void *); +static void clnt_raw_destroy(CLIENT *); +static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *); +static void clnt_raw_geterr(CLIENT *, struct rpc_err *); +static struct clnt_ops *clnt_raw_ops(void); /* * Create a client handle for memory based rpc. */ CLIENT * -clntraw_create(u_long prog, u_long vers) +clnt_raw_create(rpcprog_t prog, rpcvers_t vers) { 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; } /* @@ -100,12 +110,12 @@ clntraw_create(u_long prog, u_long 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); @@ -117,14 +127,16 @@ clntraw_create(u_long prog, u_long 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); } +/* ARGSUSED */ static enum clnt_stat -clntraw_call(CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, - xdrproc_t xresults, caddr_t resultsp, struct timeval timeout) +clnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, void *argsp, + xdrproc_t xresults, void *resultsp, struct timeval timeout) { struct clntraw_private *clp = clntraw_private; XDR *xdrs = &clp->xdr_stream; @@ -132,17 +144,24 @@ clntraw_call(CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, 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); @@ -153,7 +172,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 @@ -163,8 +182,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; @@ -174,7 +208,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 */ @@ -191,40 +225,67 @@ call_again: return (status); } +/*ARGSUSED*/ static void -clntraw_geterr(void) +clnt_raw_geterr(CLIENT *cl, struct rpc_err *err) { } +/* ARGSUSED */ static bool_t -clntraw_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) { 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(void) +clnt_raw_abort(CLIENT *cl) { } +/*ARGSUSED*/ static bool_t -clntraw_control(void) +clnt_raw_control(CLIENT *cl, u_int ui, void *str) { return (FALSE); } +/*ARGSUSED*/ static void -clntraw_destroy(void) +clnt_raw_destroy(CLIENT *cl) { } + +static struct clnt_ops * +clnt_raw_ops(void) +{ + static struct clnt_ops ops; + + /* 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 31da1bb199..5c92d0518a 100644 --- a/lib/libc/rpc/clnt_simple.c +++ b/lib/libc/rpc/clnt_simple.c @@ -28,93 +28,166 @@ * * @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro * @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_simple.c,v 1.12 2000/01/27 23:06:35 jasone Exp $ + * $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_simple.c,v 1.20 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/clnt_simple.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ /* * clnt_simple.c - * Simplified front end to rpc. + * Simplified front end to client rpc. * - * Copyright (C) 1984, Sun Microsystems, Inc. */ #include "namespace.h" +#include "reentrant.h" #include #include +#include +#include +#include #include +#include #include -#include -#include -#include -#include #include "un-namespace.h" +#include "mt_misc.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#ifndef NETIDLEN +#define NETIDLEN 32 +#endif + +struct rpc_call_private { + int valid; /* Is this entry valid ? */ + CLIENT *client; /* Client handle */ + pid_t pid; /* process-id at moment of creation */ + rpcprog_t prognum; /* Program */ + rpcvers_t versnum; /* Version */ + char host[MAXHOSTNAMELEN]; /* Servers host */ + char nettype[NETIDLEN]; /* Network type */ +}; +static struct rpc_call_private *rpc_call_private_main; + +static void rpc_call_destroy(void *); + +static void +rpc_call_destroy(void *vp) +{ + struct rpc_call_private *rcp = (struct rpc_call_private *)vp; -static struct callrpc_private { - CLIENT *client; - int socket; - int oldprognum, oldversnum, valid; - char *oldhost; -} *callrpc_private; + if (rcp) { + if (rcp->client) + CLNT_DESTROY(rcp->client); + free(rcp); + } +} -int -callrpc(char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, - char *in, xdrproc_t outproc, char *out) +/* + * 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(const char *host, /* host name */ + rpcprog_t prognum, /* program number */ + rpcvers_t versnum, /* version number */ + rpcproc_t procnum, /* procedure number */ + xdrproc_t inproc, + const char *in, + xdrproc_t outproc, /* in/out XDR procedures */ + char *out, /* recv/send data */ + const char *nettype) /* nettype */ { - struct callrpc_private *crp = callrpc_private; - struct sockaddr_in server_addr; + 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; + 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) - _close(crp->socket); - crp->socket = RPC_ANYSOCK; - if (crp->client) { - clnt_destroy(crp->client); - crp->client = NULL; + if ((nettype == NULL) || (nettype[0] == 0)) + nettype = "netpath"; + if (!(rcp->valid && rcp->pid == getpid() && + (rcp->prognum == prognum) && + (rcp->versnum == versnum) && + (!strcmp(rcp->host, host)) && + (!strcmp(rcp->nettype, nettype)))) { + int fd; + + rcp->valid = 0; + if (rcp->client) + CLNT_DESTROY(rcp->client); + /* + * Using the first successful transport for that type + */ + rcp->client = clnt_create(host, prognum, versnum, nettype); + rcp->pid = getpid(); + if (rcp->client == NULL) { + return (rpc_createerr.cf_stat); } - 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; - strcpy(crp->oldhost, host); - } + 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)) { + strcpy(rcp->host, host); + 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 dc589c6d84..0000000000 --- a/lib/libc/rpc/clnt_tcp.c +++ /dev/null @@ -1,555 +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 - * - * @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro - * @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_tcp.c,v 1.14 2000/01/27 23:06:36 jasone Exp $ - * $DragonFly: src/lib/libc/rpc/clnt_tcp.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#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(struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp, - u_int sendsz, u_int recvsz) -{ - CLIENT *h; - 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) { - 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) { - 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); - 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) - _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 - */ - 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) { - _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(CLIENT *h, u_long 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 *) h->cl_private; - 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 */ - 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; - 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; - 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(CLIENT *h, struct rpc_err *errp) -{ - struct ct_data *ct = - (struct ct_data *) h->cl_private; - - *errp = ct->ct_error; -} - -static bool_t -clnttcp_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) -{ - struct ct_data *ct = (struct ct_data *)cl->cl_private; - XDR *xdrs = &(ct->ct_xdrs); - - xdrs->x_op = XDR_FREE; - return ((*xdr_res)(xdrs, res_ptr)); -} - -static void -clnttcp_abort(void) -{ -} - - -static bool_t -clnttcp_control(CLIENT *cl, int request, char *info) -{ - struct ct_data *ct = (struct ct_data *)cl->cl_private; - 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(CLIENT *h) -{ - struct ct_data *ct = - (struct ct_data *) h->cl_private; - - if (ct->ct_closeit) { - _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(struct ct_data *ct, caddr_t buf, 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(struct ct_data *ct, caddr_t buf, int len) -{ - 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 3cec09633d..0000000000 --- a/lib/libc/rpc/clnt_udp.c +++ /dev/null @@ -1,573 +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 - * - * @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro - * @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_udp.c,v 1.15.2.1 2001/06/28 21:44:24 iedowse Exp $ - * $DragonFly: src/lib/libc/rpc/clnt_udp.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * clnt_udp.c, Implements a UDP/IP based, client side RPC. - * - * Copyright (C) 1984, Sun Microsystems, Inc. - */ - -#include "namespace.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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; - int cu_connect; /* Use connect(). */ - int cu_connected; /* Have done connect(). */ - 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(struct sockaddr_in *raddr, u_long program, u_long version, - struct timeval wait, int *sockp, u_int sendsz, u_int recvsz) -{ - CLIENT *cl; - 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) { - 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) { - 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]; - - 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; - cu->cu_connect = FALSE; - cu->cu_connected = FALSE; - 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 */ - bindresvport(*sockp, (struct sockaddr_in *)0); - /* the sockets rpc controls are non-blocking */ - _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(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)); -} - -static enum clnt_stat -clntudp_call(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 */ -{ - struct cu_data *cu = (struct cu_data *)cl->cl_private; - XDR *xdrs; - int outlen; - int inlen; - struct sockaddr *sa; - 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; - socklen_t salen; - - 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); - } - - if (cu->cu_connect && !cu->cu_connected) { - if (connect(cu->cu_sock, (struct sockaddr *)&cu->cu_raddr, - cu->cu_rlen) < 0) { - cu->cu_error.re_errno = errno; - if (fds != &readfds) - free(fds); - return (cu->cu_error.re_status = RPC_CANTSEND); - } - cu->cu_connected = 1; - } - if (cu->cu_connected) { - sa = NULL; - salen = 0; - } else { - sa = (struct sockaddr *)&cu->cu_raddr; - salen = cu->cu_rlen; - } - 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, sa, salen) - != 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; - 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(CLIENT *cl, struct rpc_err *errp) -{ - struct cu_data *cu = (struct cu_data *)cl->cl_private; - - *errp = cu->cu_error; -} - - -static bool_t -clntudp_freeres(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); - - xdrs->x_op = XDR_FREE; - return ((*xdr_res)(xdrs, res_ptr)); -} - -static void -clntudp_abort(void) /* CLIENT *h */ -{ -} - - -static bool_t -clntudp_control(CLIENT *cl, int request, char *info) -{ - struct cu_data *cu = (struct cu_data *)cl->cl_private; - 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 CLSET_CONNECT: - cu->cu_connect = *(int *)(void *)info; - 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(CLIENT *cl) -{ - struct cu_data *cu = (struct cu_data *)cl->cl_private; - - if (cu->cu_closeit) { - _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 06c2890b55..0000000000 --- a/lib/libc/rpc/clnt_unix.c +++ /dev/null @@ -1,607 +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 - * - * @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro - * @(#)clnt_unix.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/clnt_unix.c,v 1.5 2000/01/27 23:06:37 jasone Exp $ - * $DragonFly: src/lib/libc/rpc/clnt_unix.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, - u_int sendsz, u_int recvsz) -{ - CLIENT *h; - 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) { - 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) { - 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) - _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 - */ - 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) { - _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(CLIENT *h, u_long 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 *) h->cl_private; - 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 */ - 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; - 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; - 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(CLIENT *h, struct rpc_err *errp) -{ - struct ct_data *ct = - (struct ct_data *) h->cl_private; - - *errp = ct->ct_error; -} - -static bool_t -clntunix_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) -{ - struct ct_data *ct = (struct ct_data *)cl->cl_private; - XDR *xdrs = &(ct->ct_xdrs); - - xdrs->x_op = XDR_FREE; - return ((*xdr_res)(xdrs, res_ptr)); -} - -static void -clntunix_abort(void) -{ -} - - -static bool_t -clntunix_control(CLIENT *cl, int request, char *info) -{ - struct ct_data *ct = (struct ct_data *)cl->cl_private; - 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(CLIENT *h) -{ - struct ct_data *ct = - (struct ct_data *) h->cl_private; - - if (ct->ct_closeit) { - _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(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(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(struct ct_data *ct, caddr_t buf, 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(struct ct_data *ct, caddr_t buf, int len) -{ - 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 0000000000..8bc4e6f221 --- /dev/null +++ b/lib/libc/rpc/clnt_vc.c @@ -0,0 +1,809 @@ +/* + * 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 + * @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro; 2.2 88/08/01 4.0 RPCSRC + * @(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro + * $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/clnt_vc.c,v 1.20 2006/09/09 22:18:57 mbr Exp $ + * $DragonFly$ + */ + +/* + * 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 "reentrant.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "un-namespace.h" +#include "rpc_com.h" +#include "mt_misc.h" + +#define MCALL_MSG_SIZE 24 + +struct cmessage { + struct cmsghdr cmsg; + struct cmsgcred cmcred; +}; + +static void clnt_vc_abort(CLIENT *); +static enum clnt_stat clnt_vc_call(CLIENT *, rpcproc_t, xdrproc_t, void *, + xdrproc_t, void *, struct timeval); +static bool_t clnt_vc_control(CLIENT *, u_int, void *); +static void clnt_vc_destroy(CLIENT *); +static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *); +static void clnt_vc_geterr(CLIENT *, struct rpc_err *); +static struct clnt_ops *clnt_vc_ops(void); +static int __msgread(int, void *, size_t); +static int __msgwrite(int, void *, size_t); +static int read_vc(void *, void *, int); +static bool_t time_not_ok(struct timeval *); +static int write_vc(void *, void *, int); + +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 */ +}; + +/* + * 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; +static cond_t *vc_cv; +#define release_fd_lock(fd, mask) { \ + mutex_lock(&clnt_fd_lock); \ + 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(int fd, /* open file descriptor */ + const struct netbuf *raddr, /* servers address */ + const rpcprog_t prog, /* program number */ + const 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)) { + 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); + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); + 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); + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); + goto err; + } + } + mutex_unlock(&clnt_fd_lock); + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); + if (!__rpc_fd2sockinfo(fd, &si)) + goto err; + + 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 + */ + 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) { + _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(ct, sizeof (struct ct_data)); + } + if (cl) + mem_free(cl, sizeof (CLIENT)); + } + return ((CLIENT *)NULL); +} + +static enum clnt_stat +clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr, + xdrproc_t xdr_results, void *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; + 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; + 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(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(CLIENT *cl, xdrproc_t xdr_res, void *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(CLIENT *cl) +{ +} + +static bool_t +clnt_vc_control(CLIENT *cl, u_int request, void *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 *)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: + memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len); + break; + case CLGET_FD: + *(int *)info = ct->ct_fd; + break; + case CLGET_SVC_ADDR: + /* The caller should not free this memory area */ + *(struct netbuf *)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 *)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 *)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 *)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 *)info); + break; + + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the fourth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_int32_t *)info = + ntohl(*(u_int32_t *)(void *)(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 *)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(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) { + _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(void *ctp, void *buf, int len) +{ + struct sockaddr sa; + socklen_t sal; + struct ct_data *ct = (struct ct_data *)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(void *ctp, void *buf, int len) +{ + struct sockaddr sa; + socklen_t sal; + struct ct_data *ct = (struct ct_data *)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 = (char *)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 = (char *)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(void) +{ + static struct clnt_ops ops; + 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(struct timeval *t) +{ + return (t->tv_sec <= -1 || t->tv_sec > 100000000 || + t->tv_usec <= -1 || t->tv_usec > 1000000); +} + +static int +__msgread(int sock, void *buf, size_t cnt) +{ + struct iovec iov[1]; + struct msghdr msg; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(struct cmsgcred))]; + } 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 = CMSG_SPACE(sizeof(struct cmsgcred)); + msg.msg_flags = 0; + + return(_recvmsg(sock, &msg, 0)); +} + +static int +__msgwrite(int sock, void *buf, size_t cnt) +{ + struct iovec iov[1]; + struct msghdr msg; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(struct cmsgcred))]; + } 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 = CMSG_LEN(sizeof(struct cmsgcred)); + + 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 = CMSG_SPACE(sizeof(struct cmsgcred)); + 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 11a5065f59..96daef4585 100644 --- a/lib/libc/rpc/crypt_client.c +++ b/lib/libc/rpc/crypt_client.c @@ -29,21 +29,18 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $ + * $FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.9 2003/02/16 17:29:10 nectar Exp $ * $DragonFly: src/lib/libc/rpc/crypt_client.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ - * - * $FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $ */ +#include "namespace.h" +#include #include #include #include #include #include - -#ifndef KEYSERVSOCK -#define KEYSERVSOCK "/var/run/keyservsock" -#endif +#include "un-namespace.h" int _des_crypt_call(char *buf, int len, struct desparams *dparms) @@ -51,12 +48,27 @@ _des_crypt_call(char *buf, int len, struct desparams *dparms) CLIENT *clnt; desresp *result_1; desargs des_crypt_1_arg; - int stat; + struct netconfig *nconf; + void *localhandle; + int stat; - clnt = clnt_create(KEYSERVSOCK, CRYPT_PROG, CRYPT_VERS, "unix"); + nconf = NULL; + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } + if (nconf == NULL) { + warnx("getnetconfig: %s", nc_sperror()); + return(DESERR_HWERROR); + } + clnt = clnt_tp_create(NULL, CRYPT_PROG, CRYPT_VERS, nconf); if (clnt == (CLIENT *) NULL) { + endnetconfig(localhandle); return(DESERR_HWERROR); } + endnetconfig(localhandle); des_crypt_1_arg.desbuf.desbuf_len = len; des_crypt_1_arg.desbuf.desbuf_val = buf; @@ -79,7 +91,7 @@ _des_crypt_call(char *buf, int len, struct desparams *dparms) bcopy(result_1->des_ivec, dparms->des_ivec, 8); } - clnt_freeres(clnt, xdr_desresp, (char *)result_1); + clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1); clnt_destroy(clnt); return(stat); diff --git a/lib/libc/rpc/get_myaddress.c b/lib/libc/rpc/get_myaddress.c deleted file mode 100644 index 165e5a54d4..0000000000 --- a/lib/libc/rpc/get_myaddress.c +++ /dev/null @@ -1,115 +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 - * - * @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro - * @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/get_myaddress.c,v 1.18.2.1 2003/01/01 23:55:34 jdp Exp $ - * $DragonFly: src/lib/libc/rpc/get_myaddress.c,v 1.5 2007/11/25 01:28:22 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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(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) && - ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr - != 0) || - (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; - } - _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 0000000000..8b5851bbd5 --- /dev/null +++ b/lib/libc/rpc/getnetconfig.3 @@ -0,0 +1,223 @@ +.\" @(#)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: src/lib/libc/rpc/getnetconfig.3,v 1.4 2002/12/19 09:40:23 ru Exp $ +.\" $DragonFly$ +.\" Copyright 1989 AT&T +.Dd Novemeber 15, 2008 +.Dt GETNETCONFIG 3 +.Os +.Sh NAME +.Nm getnetconfig , +.Nm setnetconfig , +.Nm endnetconfig , +.Nm getnetconfigent , +.Nm freenetconfigent , +.Nm nc_perror , +.Nm nc_sperror +.Nd get network configuration database entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In netconfig.h +.Ft "struct netconfig *" +.Fn getnetconfig "void *handlep" +.Ft "void *" +.Fn setnetconfig "void" +.Ft int +.Fn endnetconfig "void *handlep" +.Ft "struct netconfig *" +.Fn getnetconfigent "const char *netid" +.Ft void +.Fn freenetconfigent "struct netconfig *netconfigp" +.Ft void +.Fn nc_perror "const char *msg" +.Ft "char *" +.Fn nc_sperror "void" +.Sh DESCRIPTION +The library routines described on this page +provide the application access to +the system network configuration database, +.Pa /etc/netconfig . +The +.Fn getnetconfig +function +returns a pointer to the +current entry in the +netconfig +database, formatted as a +.Ft "struct netconfig" . +Successive calls will return successive netconfig +entries in the netconfig database. +The +.Fn getnetconfig +function +can be used to search the entire netconfig +file. +The +.Fn getnetconfig +function +returns +.Dv NULL +at the end of the file. +The +.Fa handlep +argument +is the handle obtained through +.Fn setnetconfig . +.Pp +A call to +.Fn setnetconfig +has the effect of +.Dq binding +to or +.Dq rewinding +the netconfig database. +The +.Fn setnetconfig +function +must be called before the first call to +.Fn getnetconfig +and may be called at any other time. +The +.Fn setnetconfig +function +need not be called before a call to +.Fn getnetconfigent . +The +.Fn setnetconfig +function +returns a unique handle to be used by +.Fn getnetconfig . +.Pp +The +.Fn endnetconfig +function +should be called when processing is complete to release resources for reuse. +The +.Fa handlep +argument +is the handle obtained through +.Fn setnetconfig . +Programmers should be aware, however, that the last call to +.Fn endnetconfig +frees all memory allocated by +.Fn getnetconfig +for the +.Ft "struct netconfig" +data structure. +The +.Fn endnetconfig +function +may not be called before +.Fn setnetconfig . +.Pp +The +.Fn getnetconfigent +function +returns a pointer +to the netconfig structure corresponding +to +.Fa netid . +It returns +.Dv NULL +if +.Fa netid +is invalid +(that is, does not name an entry in the netconfig database). +.Pp +The +.Fn freenetconfigent +function +frees the netconfig structure pointed to by +.Fa netconfigp +(previously returned by +.Fn getnetconfigent ) . +.Pp +The +.Fn nc_perror +function +prints a message to the standard error indicating why any of the +above routines failed. +The message is prepended with the string +.Fa msg +and a colon. +A newline character is appended at the end of the message. +.Pp +The +.Fn nc_sperror +function +is similar to +.Fn nc_perror +but instead of sending the message +to the standard error, will return a pointer to a string that +contains the error message. +.Pp +The +.Fn nc_perror +and +.Fn nc_sperror +functions +can also be used with the +.Ev NETPATH +access routines defined in +.Xr getnetpath 3 . +.Sh RETURN VALUES +The +.Fn setnetconfig +function +returns a unique handle to be used by +.Fn getnetconfig . +In the case of an error, +.Fn setnetconfig +returns +.Dv NULL +and +.Fn nc_perror +or +.Fn nc_sperror +can be used to print the reason for failure. +.Pp +The +.Fn getnetconfig +function +returns a pointer to the current entry in the netconfig +database, formatted as a +.Ft "struct netconfig" . +The +.Fn getnetconfig +function +returns +.Dv NULL +at the end of the file, or upon failure. +.Pp +The +.Fn endnetconfig +function +returns 0 on success and \-1 on failure +(for example, if +.Fn setnetconfig +was not called previously). +.Pp +On success, +.Fn getnetconfigent +returns a pointer to the +.Ft "struct netconfig" +structure corresponding to +.Fa netid ; +otherwise it returns +.Dv NULL . +.Pp +The +.Fn nc_sperror +function +returns a pointer to a buffer which contains the error message string. +This buffer is overwritten on each call. +In multithreaded applications, this buffer is +implemented as thread-specific data. +.Sh FILES +.Bl -tag -width /etc/netconfig -compact +.It Pa /etc/netconfig +.El +.Sh SEE ALSO +.Xr getnetpath 3 , +.Xr netconfig 5 diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c new file mode 100644 index 0000000000..0e30c7275c --- /dev/null +++ b/lib/libc/rpc/getnetconfig.c @@ -0,0 +1,697 @@ +/* + * 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 + * + * @(#)getnetconfig.c 1.12 91/12/19 SMI + * $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/getnetconfig.c,v 1.14 2007/09/20 22:35:24 matteo Exp $ + * $DragonFly$ + */ + +/* + * Copyright (c) 1989 by Sun Microsystems, Inc. + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#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 */ +#define NC_NOTFOUND ENOPROTOOPT /* specified netid was not found */ + +/* + * semantics as strings (should be in netconfig.h) + */ +#define NC_TPI_CLTS_S "tpi_clts" +#define NC_TPI_COTS_S "tpi_cots" +#define NC_TPI_COTS_ORD_S "tpi_cots_ord" +#define NC_TPI_RAW_S "tpi_raw" + +/* + * flags as characters (also should be in netconfig.h) + */ +#define NC_NOFLAG_C '-' +#define NC_VISIBLE_C 'v' +#define NC_BROADCAST_C 'b' + +/* + * Character used to indicate there is no name-to-address lookup library + */ +#define NC_NOLOOKUP "-" + +static const char * const _nc_errors[] = { + "Netconfig database not found", + "Not enough memory", + "Not initialized", + "Netconfig database has invalid format", + "Netid not found in netconfig database" +}; + +struct netconfig_info { + int eof; /* all entries has been read */ + int ref; /* # of times setnetconfig() has been called */ + struct netconfig_list *head; /* head of the list */ + struct netconfig_list *tail; /* last of the list */ +}; + +struct netconfig_list { + char *linep; /* hold line read from netconfig */ + struct netconfig *ncp; + struct netconfig_list *next; +}; + +struct netconfig_vars { + int valid; /* token that indicates a valid netconfig_vars */ + int flag; /* first time flag */ + struct netconfig_list *nc_configs; /* pointer to the current netconfig entry */ +}; + +#define NC_VALID 0xfeed +#define NC_STORAGE 0xf00d +#define NC_INVALID 0 + + +static int *__nc_error(void); +static int parse_ncp(char *, struct netconfig *); +static struct netconfig *dup_ncp(struct netconfig *); + + +static FILE *nc_file; /* for netconfig db */ +static struct netconfig_info ni = { 0, 0, NULL, NULL}; + +#define MAXNETCONFIGLINE 1000 + +static int * +__nc_error(void) +{ + static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER; + static thread_key_t nc_key = 0; + static int nc_error = 0; + int error, *nc_addr; + + /* + * Use the static `nc_error' if we are the main thread + * (including non-threaded programs), or if an allocation + * fails. + */ + if (thr_main()) + return (&nc_error); + if (nc_key == 0) { + error = 0; + mutex_lock(&nc_lock); + if (nc_key == 0) + error = thr_keycreate(&nc_key, free); + mutex_unlock(&nc_lock); + if (error) + return (&nc_error); + } + if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { + nc_addr = (int *)malloc(sizeof (int)); + if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { + if (nc_addr) + free(nc_addr); + return (&nc_error); + } + *nc_addr = 0; + } + return (nc_addr); +} + +#define nc_error (*(__nc_error())) +/* + * A call to setnetconfig() establishes a /etc/netconfig "session". A session + * "handle" is returned on a successful call. At the start of a session (after + * a call to setnetconfig()) searches through the /etc/netconfig database will + * proceed from the start of the file. The session handle must be passed to + * getnetconfig() to parse the file. Each call to getnetconfig() using the + * current handle will process one subsequent entry in /etc/netconfig. + * setnetconfig() must be called before the first call to getnetconfig(). + * (Handles are used to allow for nested calls to setnetpath()). + * + * A new session is established with each call to setnetconfig(), with a new + * handle being returned on each call. Previously established sessions remain + * active until endnetconfig() is called with that session's handle as an + * argument. + * + * setnetconfig() need *not* be called before a call to getnetconfigent(). + * setnetconfig() returns a NULL pointer on failure (for example, if + * the netconfig database is not present). + */ +void * +setnetconfig(void) +{ + 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(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(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(const char *netid) +{ + FILE *file; /* NETCONFIG db's file pointer */ + char *linep; /* holds current netconfig line */ + char *stringp; /* temporary string pointer */ + struct netconfig *ncp = NULL; /* returned value */ + struct netconfig_list *list; /* pointer to cache list */ + + nc_error = NC_NOTFOUND; /* default error. */ + if (netid == NULL || strlen(netid) == 0) { + return (NULL); + } + + if (strcmp(netid, "unix") == 0) { + fprintf(stderr, "The local transport is called \"unix\" "); + fprintf(stderr, "in /etc/netconfig.\n"); + fprintf(stderr, "Please change this to \"local\" manually "); + fprintf(stderr, "or run mergemaster(8).\n"); + fprintf(stderr, "See UPDATING entry 20021216 for details.\n"); + fprintf(stderr, "Continuing in 10 seconds\n\n"); + fprintf(stderr, "This warning will be removed 20030301\n"); + sleep(10); + + } + + /* + * Look up table if the entries have already been read and parsed in + * getnetconfig(), then copy this entry into a buffer and return it. + * If we cannot find the entry in the current list and there are more + * entries in the netconfig db that has not been read, we then read the + * db and try find the match netid. + * If all the netconfig db has been read and placed into the list and + * there is no match for the netid, return NULL. + */ + if (ni.head != NULL) { + for (list = ni.head; list; list = list->next) { + if (strcmp(list->ncp->nc_netid, netid) == 0) { + return(dup_ncp(list->ncp)); + } + } + if (ni.eof == 1) /* that's all the entries */ + return(NULL); + } + + + if ((file = fopen(NETCONFIG, "r")) == NULL) { + nc_error = NC_NONETCONFIG; + return (NULL); + } + + if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) { + fclose(file); + nc_error = NC_NOMEM; + return (NULL); + } + do { + ptrdiff_t len; + char *tmpp; /* tmp string pointer */ + + do { + if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) { + break; + } + } while (*stringp == '#'); + if (stringp == NULL) { /* eof */ + break; + } + if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */ + nc_error = NC_BADFILE; + break; + } + if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */ + strncmp(stringp, netid, (size_t)len) == 0) { + if ((ncp = (struct netconfig *) + malloc(sizeof (struct netconfig))) == NULL) { + break; + } + ncp->nc_lookups = NULL; + if (parse_ncp(linep, ncp) == -1) { + free(ncp); + ncp = NULL; + } + break; + } + } while (stringp != NULL); + if (ncp == NULL) { + free(linep); + } + fclose(file); + return(ncp); +} + +/* + * freenetconfigent(netconfigp) frees the netconfig structure pointed to by + * netconfigp (previously returned by getnetconfigent()). + */ + +void +freenetconfigent(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(char *stringp, /* string to parse */ + struct netconfig *ncp) /* where to put results */ +{ + char *tokenp; /* for processing tokens */ + char *lasts; + char **nc_lookups; + + 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); + ncp->nc_lookups = NULL; + ncp->nc_nlookups = 0; + while ((cp = tokenp) != NULL) { + if ((nc_lookups = realloc(ncp->nc_lookups, + (ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) { + free(ncp->nc_lookups); + ncp->nc_lookups = NULL; + return (-1); + } + tokenp = _get_next_token(cp, ','); + ncp->nc_lookups = nc_lookups; + ncp->nc_lookups[ncp->nc_nlookups++] = cp; + } + } + return (0); +} + + +/* + * Returns a string describing the reason for failure. + */ +char * +nc_sperror(void) +{ + const char *message; + + switch(nc_error) { + case NC_NONETCONFIG: + message = _nc_errors[0]; + break; + case NC_NOMEM: + message = _nc_errors[1]; + break; + case NC_NOTINIT: + message = _nc_errors[2]; + break; + case NC_BADFILE: + message = _nc_errors[3]; + break; + case NC_NOTFOUND: + message = _nc_errors[4]; + break; + default: + message = "Unknown network selection error"; + } + /* LINTED const castaway */ + return ((char *)message); +} + +/* + * Prints a message onto standard error describing the reason for failure. + */ +void +nc_perror(const char *s) +{ + fprintf(stderr, "%s: %s\n", s, nc_sperror()); +} + +/* + * Duplicates the matched netconfig buffer. + */ +static struct netconfig * +dup_ncp(struct netconfig *ncp) +{ + struct netconfig *p; + char *tmp; + u_int i; + + if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL) + return(NULL); + if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) { + free(tmp); + return(NULL); + } + /* + * First we dup all the data from matched netconfig buffer. Then we + * adjust some of the member pointer to a pre-allocated buffer where + * contains part of the data. + * To follow the convention used in parse_ncp(), we store all the + * necessary information in the pre-allocated buffer and let each + * of the netconfig char pointer member point to the right address + * in the buffer. + */ + *p = *ncp; + p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid); + tmp = strchr(tmp, '\0') + 1; + p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly); + tmp = strchr(tmp, '\0') + 1; + p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto); + tmp = strchr(tmp, '\0') + 1; + p->nc_device = (char *)strcpy(tmp,ncp->nc_device); + p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *)); + if (p->nc_lookups == NULL) { + free(p->nc_netid); + free(p); + return(NULL); + } + for (i=0; i < p->nc_nlookups; i++) { + tmp = strchr(tmp, '\0') + 1; + p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]); + } + return(p); +} diff --git a/lib/libc/rpc/getnetpath.3 b/lib/libc/rpc/getnetpath.3 new file mode 100644 index 0000000000..d60e707d6c --- /dev/null +++ b/lib/libc/rpc/getnetpath.3 @@ -0,0 +1,171 @@ +.\" @(#)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: src/lib/libc/rpc/getnetpath.3,v 1.5 2002/12/18 12:45:10 ru Exp $ +.\" $DragonFly$ +.\" Copyright 1989 AT&T +.Dd November 15, 2008 +.Dt GETNETPATH 3 +.Os +.Sh NAME +.Nm getnetpath , +.Nm setnetpath , +.Nm endnetpath +.Nd get +.Pa /etc/netconfig +entry corresponding to +.Ev NETPATH +component +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In netconfig.h +.Ft "struct netconfig *" +.Fn getnetpath "void *handlep" +.Ft "void *" +.Fn setnetpath "void" +.Ft int +.Fn endnetpath "void *handlep" +.Sh DESCRIPTION +The routines described in this page provide the application access to the system +network configuration database, +.Pa /etc/netconfig , +as it is +.Dq filtered +by the +.Ev NETPATH +environment variable (see +.Xr environ 7 ) . +See +.Xr getnetconfig 3 +for other routines that also access the +network configuration database directly. +The +.Ev NETPATH +variable is a list of colon-separated network identifiers. +.Pp +The +.Fn getnetpath +function +returns a pointer to the +netconfig database entry corresponding to the first valid +.Ev NETPATH +component. +The netconfig entry is formatted as a +.Ft "struct netconfig" . +On each subsequent call, +.Fn getnetpath +returns a pointer to the netconfig entry that corresponds to the next +valid +.Ev NETPATH +component. +The +.Fn getnetpath +function +can thus be used to search the netconfig database for all networks +included in the +.Ev NETPATH +variable. +When +.Ev NETPATH +has been exhausted, +.Fn getnetpath +returns +.Dv NULL . +.Pp +A call to +.Fn setnetpath +.Dq binds +to or +.Dq rewinds +.Ev NETPATH . +The +.Fn setnetpath +function +must be called before the first call to +.Fn getnetpath +and may be called at any other time. +It returns a handle that is used by +.Fn getnetpath . +.Pp +The +.Fn getnetpath +function +silently ignores invalid +.Ev NETPATH +components. +A +.Ev NETPATH +component is invalid if there is no corresponding +entry in the netconfig database. +.Pp +If the +.Ev NETPATH +variable is unset, +.Fn getnetpath +behaves as if +.Ev NETPATH +were set to the sequence of +.Dq default +or +.Dq visible +networks in the netconfig database, in the +order in which they are listed. +.\"This proviso holds also for this +.\"whole manpage. +.Pp +The +.Fn endnetpath +function +may be called to +.Dq unbind +from +.Ev NETPATH +when processing is complete, releasing resources for reuse. +Programmers should be aware, however, that +.Fn endnetpath +frees all memory allocated by +.Fn getnetpath +for the struct netconfig data structure. +.Sh RETURN VALUES +The +.Fn setnetpath +function +returns a handle that is used by +.Fn getnetpath . +In case of an error, +.Fn setnetpath +returns +.Dv NULL . +.Pp +The +.Fn endnetpath +function +returns 0 on success and \-1 on failure +(for example, if +.Fn setnetpath +was not called previously). +The +.Fn nc_perror +or +.Fn nc_sperror +function +can be used to print out the reason for failure. +See +.Xr getnetconfig 3 . +.Pp +When first called, +.Fn getnetpath +returns a pointer to the netconfig database entry corresponding to the first +valid +.Ev NETPATH +component. +When +.Ev NETPATH +has been exhausted, +.Fn getnetpath +returns +.Dv NULL . +.Sh SEE ALSO +.Xr getnetconfig 3 , +.Xr netconfig 5 , +.Xr environ 7 diff --git a/lib/libc/rpc/getnetpath.c b/lib/libc/rpc/getnetpath.c new file mode 100644 index 0000000000..407600f65c --- /dev/null +++ b/lib/libc/rpc/getnetpath.c @@ -0,0 +1,270 @@ +/* + * 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 + * + * @(#)getnetpath.c 1.11 91/12/19 SMI + * $NetBSD: getnetpath.c,v 1.3 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/getnetpath.c,v 1.8 2007/09/20 22:35:24 matteo Exp $ + * $DragonFly$ + */ + +/* + * Copyright (c) 1989 by Sun Microsystems, Inc. + */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#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(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(void) +{ + + 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) { + free(np_sessionp); + syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); + goto failed; + } + np_sessionp->valid = NP_VALID; + np_sessionp->ncp_list = NULL; + if ((npp = getenv(NETPATH)) == NULL) { + np_sessionp->netpath = NULL; + } else { + endnetconfig(np_sessionp->nc_handlep);/* won't need nc session*/ + np_sessionp->nc_handlep = NULL; + if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL) + goto failed; + else { + strcpy(np_sessionp->netpath, npp); + } + } + np_sessionp->netpath_start = np_sessionp->netpath; + return ((void *)np_sessionp); + +failed: + free(np_sessionp); + return (NULL); +} + +/* + * 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(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(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(char *npp, /* string */ + int token) /* char to parse string for */ +{ + char *cp; /* char pointer */ + char *np; /* netpath pointer */ + char *ep; /* escape pointer */ + + if ((cp = strchr(npp, token)) == NULL) { + return (NULL); + } + /* + * did find a token, but it might be escaped. + */ + if ((cp > npp) && (cp[-1] == '\\')) { + /* if slash was also escaped, carry on, otherwise find next token */ + if ((cp > npp + 1) && (cp[-2] != '\\')) { + /* shift r-o-s onto the escaped token */ + strcpy(&cp[-1], cp); /* XXX: overlapping string copy */ + /* + * Do a recursive call. + * We don't know how many escaped tokens there might be. + */ + return (_get_next_token(cp, token)); + } + } + + *cp++ = '\0'; /* null-terminate token */ + /* get rid of any backslash escapes */ + ep = npp; + while ((np = strchr(ep, '\\')) != 0) { + if (np[1] == '\\') + np++; + strcpy(np, (ep = &np[1])); /* XXX: overlapping string copy */ + } + return (cp); /* return ptr to r-o-s */ +} diff --git a/lib/libc/rpc/getpublickey.c b/lib/libc/rpc/getpublickey.c index 0677a9e45d..81eedf8a44 100644 --- a/lib/libc/rpc/getpublickey.c +++ b/lib/libc/rpc/getpublickey.c @@ -27,7 +27,7 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * $FreeBSD: src/lib/libc/rpc/getpublickey.c,v 1.2.6.1 2000/09/20 04:43:11 jkh Exp $ + * $FreeBSD: src/lib/libc/rpc/getpublickey.c,v 1.9 2006/02/28 16:02:26 deischen Exp $ * $DragonFly: src/lib/libc/rpc/getpublickey.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ * * @(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro @@ -41,6 +41,7 @@ /* * Public key lookup routines */ +#include "namespace.h" #include #include #include @@ -49,6 +50,7 @@ #include #include #include +#include "un-namespace.h" #define PKFILE "/etc/publickey" @@ -60,8 +62,8 @@ int (*__getpublickey_LOCAL)() = 0; /* * Get somebody's public key */ -int -__getpublickey_real(char *netname, char *publickey) +static int +__getpublickey_real(const char *netname, char *publickey) { char lookup[3 * HEXKEYBYTES]; char *p; @@ -86,7 +88,7 @@ __getpublickey_real(char *netname, char *publickey) */ int -getpublicandprivatekey(char *key, char *ret) +getpublicandprivatekey(const char *key, char *ret) { char buf[1024]; /* big enough */ char *res; @@ -162,7 +164,7 @@ getpublicandprivatekey(char *key, char *ret) } int -getpublickey(char *netname, char *publickey) +getpublickey(const char *netname, char *publickey) { if (__getpublickey_LOCAL != NULL) return(__getpublickey_LOCAL(netname, publickey)); diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3 index b2d0a8a6bc..35107861c2 100644 --- a/lib/libc/rpc/getrpcent.3 +++ b/lib/libc/rpc/getrpcent.3 @@ -1,5 +1,6 @@ .\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI -.\" $FreeBSD: src/lib/libc/rpc/getrpcent.3,v 1.11.2.3 2001/12/14 18:33:56 ru Exp $ +.\" $NetBSD: getrpcent.3,v 1.6 1998/02/05 18:49:06 perry Exp $ +.\" $FreeBSD: src/lib/libc/rpc/getrpcent.3,v 1.18 2005/01/20 09:17:04 ru Exp $ .\" $DragonFly: src/lib/libc/rpc/getrpcent.3,v 1.4 2007/08/18 20:48:47 swildner Exp $ .\" .Dd December 14, 1987 @@ -32,14 +33,14 @@ The .Fn getrpcbyname , and .Fn getrpcbynumber -functions each return a pointer to an object with the +functions +each return a pointer to an object with the following structure containing the broken-out fields of a line in the rpc program number data base, -.Pa /etc/rpc . +.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 */ @@ -47,36 +48,44 @@ 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. +function +reads the next line of the file, opening the file if necessary. +.Pp The .Fn setrpcent -function opens and rewinds the file. If the +function +opens and rewinds the file. +If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to .Fn getrpcent (either directly, or indirectly through one of the other -.Fn getrpcent -function family. +.Dq getrpc +calls). .Pp +The .Fn endrpcent +function closes the file. .Pp +The .Fn getrpcbyname and .Fn getrpcbynumber +functions sequentially search from the beginning of the file until a matching rpc program name or program number is found, or until end-of-file is encountered. @@ -90,7 +99,7 @@ A pointer is returned on .Dv EOF or error. -.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 c5c6eb49c4..f5239d4d71 100644 --- a/lib/libc/rpc/getrpcent.c +++ b/lib/libc/rpc/getrpcent.c @@ -28,7 +28,8 @@ * Mountain View, California 94043 * * @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro - * $FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.10 1999/08/28 00:00:39 peter Exp $ + * $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ + * $FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.14 2003/02/27 13:40:01 nectar Exp $ * $DragonFly: src/lib/libc/rpc/getrpcent.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -36,20 +37,30 @@ * Copyright (c) 1984 by Sun Microsystems, Inc. */ +#include "namespace.h" +#include + +#include +#include + +#include +#include #include #include -#include #include + #include #ifdef YP #include #include #endif +#include "un-namespace.h" +#include "libc_private.h" /* * Internet version. */ -struct rpcdata { +static struct rpcdata { FILE *rpcf; int stayopen; #define MAXALIASES 35 @@ -63,16 +74,15 @@ struct rpcdata { #endif } *rpcdata; +static struct rpcent *interpret(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(void); static struct rpcdata * _rpcdata(void) @@ -89,12 +99,12 @@ _rpcdata(void) struct rpcent * getrpcbynumber(int number) { - struct rpcdata *d = _rpcdata(); - struct rpcent *p; #ifdef YP int reason; char adrstr[16]; #endif + struct rpcent *p; + struct rpcdata *d = _rpcdata(); if (d == 0) return (0); @@ -121,8 +131,9 @@ getrpcbynumber(int number) } no_yp: #endif /* YP */ + setrpcent(0); - while ((p = getrpcent())) { + while ((p = getrpcent()) != NULL) { if (p->r_number == number) break; } @@ -136,8 +147,10 @@ getrpcbyname(char *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++) { @@ -249,12 +262,14 @@ no_yp: } static struct rpcent * -interpret(char *val, int len) +interpret(char *val, size_t len) { struct rpcdata *d = _rpcdata(); char *p; char *cp, **q; + assert(val != NULL); + if (d == 0) return (0); strncpy(d->line, val, BUFSIZ); diff --git a/lib/libc/rpc/getrpcport.c b/lib/libc/rpc/getrpcport.c index 377faadce9..09aa1f70a1 100644 --- a/lib/libc/rpc/getrpcport.c +++ b/lib/libc/rpc/getrpcport.c @@ -28,7 +28,8 @@ * * @(#)getrpcport.c 1.3 87/08/11 SMI * @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/getrpcport.c,v 1.10 1999/08/28 00:00:40 peter Exp $ + * $NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $ + * $FreeBSD: src/lib/libc/rpc/getrpcport.c,v 1.13 2004/10/16 06:11:34 obrien Exp $ * $DragonFly: src/lib/libc/rpc/getrpcport.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ */ @@ -36,12 +37,18 @@ * Copyright (c) 1985 by Sun Microsystems, Inc. */ +#include "namespace.h" +#include +#include + +#include +#include #include #include + #include #include -#include -#include +#include "un-namespace.h" int getrpcport(char *host, int prognum, int versnum, int proto) @@ -49,12 +56,18 @@ getrpcport(char *host, int prognum, int versnum, int 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 9409561bbb..bb0e61930d 100644 --- a/lib/libc/rpc/key_call.c +++ b/lib/libc/rpc/key_call.c @@ -5,36 +5,35 @@ * 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. + * Copyright (c) 1986-1991 by Sun Microsystems Inc. * - * $FreeBSD: src/lib/libc/rpc/key_call.c,v 1.3 2000/01/27 23:06:39 jasone Exp $ + * @(#)key_call.c 1.25 94/04/24 SMI + * $FreeBSD: src/lib/libc/rpc/key_call.c,v 1.16 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/key_call.c,v 1.6 2005/11/13 12:27:04 swildner Exp $ */ -#ident "@(#)key_call.c 1.25 94/04/24 SMI" - /* * key_call.c, Interface to keyserver * @@ -45,6 +44,7 @@ */ #include "namespace.h" +#include "reentrant.h" #include #include #include @@ -54,12 +54,14 @@ #include #include #include +#include #include #include #include #include #include #include "un-namespace.h" +#include "mt_misc.h" #define KEY_TIMEOUT 5 /* per-try timeout in seconds */ @@ -84,15 +86,16 @@ cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0; cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0; des_block *(*__key_gendes_LOCAL)() = 0; -static int key_call ( u_long, xdrproc_t, char *, xdrproc_t, char * ); +static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *); int key_setsecret(const char *secretkey) { keystatus status; - if (!key_call((u_long) KEY_SET, xdr_keybuf, (char *) secretkey, - xdr_keystatus, (char *)&status)) { + if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf, + (void *)secretkey, + (xdrproc_t)xdr_keystatus, &status)) { return (-1); } if (status != KEY_SUCCESS) { @@ -116,8 +119,8 @@ key_secretkey_is_set(void) struct key_netstres kres; memset((void*)&kres, 0, sizeof (kres)); - if (key_call((u_long) KEY_NET_GET, xdr_void, (char *)NULL, - xdr_key_netstres, (char *) &kres) && + if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_key_netstres, &kres) && (kres.status == KEY_SUCCESS) && (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { /* avoid leaving secret key in memory */ @@ -136,8 +139,8 @@ key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) arg.remotename = remotename; arg.remotekey = *remotekey; arg.deskey = *deskey; - if (!key_call((u_long)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, - xdr_cryptkeyres, (char *)&res)) { + if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { @@ -157,8 +160,8 @@ key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) arg.remotename = remotename; arg.remotekey = *remotekey; arg.deskey = *deskey; - if (!key_call((u_long)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, - xdr_cryptkeyres, (char *)&res)) { + if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { @@ -177,8 +180,8 @@ key_encryptsession(const char *remotename, des_block *deskey) arg.remotename = (char *) remotename; arg.deskey = *deskey; - if (!key_call((u_long)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, - xdr_cryptkeyres, (char *)&res)) { + if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { @@ -197,8 +200,8 @@ key_decryptsession(const char *remotename, des_block *deskey) arg.remotename = (char *) remotename; arg.deskey = *deskey; - if (!key_call((u_long)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, - xdr_cryptkeyres, (char *)&res)) { + if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { @@ -212,21 +215,21 @@ key_decryptsession(const char *remotename, des_block *deskey) int key_gendes(des_block *key) { - if (!key_call((u_long)KEY_GEN, xdr_void, (char *)NULL, - xdr_des_block, (char *)key)) { + if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_des_block, key)) { return (-1); } return (0); } int -key_setnet(struct netstarg *arg) +key_setnet(struct key_netstarg *arg) { keystatus status; - if (!key_call((u_long) KEY_NET_PUT, xdr_key_netstarg, (char *) arg, - xdr_keystatus, (char *) &status)){ + if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg, + (xdrproc_t)xdr_keystatus, &status)){ return (-1); } @@ -243,8 +246,8 @@ key_get_conv(char *pkey, des_block *deskey) { cryptkeyres res; - if (!key_call((u_long) KEY_GET_CONV, xdr_keybuf, pkey, - xdr_cryptkeyres, (char *)&res)) { + if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey, + (xdrproc_t)xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { @@ -262,7 +265,6 @@ struct key_call_private { }; static struct key_call_private *key_call_private_main = NULL; -#ifdef foo static void key_call_destroy(void *vp) { @@ -274,7 +276,6 @@ key_call_destroy(void *vp) free(kcp); } } -#endif /* * Keep the handle cached. This call may be made quite often. @@ -282,21 +283,39 @@ key_call_destroy(void *vp) static CLIENT * getkeyserv_handle(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; #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; } @@ -306,16 +325,6 @@ getkeyserv_handle(int vers) kcp->client = NULL; } - 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()) { @@ -333,11 +342,36 @@ getkeyserv_handle(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 (uname(&u) == -1) + { + endnetconfig(localhandle); + return ((CLIENT *) NULL); + } + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { + /* + * We use COTS_ORD here so that the caller can + * find out immediately if the server is dead. + */ + if (nconf->nc_semantics == NC_TPI_COTS_ORD) { + kcp->client = clnt_tp_create(u.nodename, + KEY_PROG, vers, nconf); + if (kcp->client) + break; + } else { + tpconf = nconf; + } + } + } + if ((kcp->client == (CLIENT *) NULL) && (tpconf)) + /* Now, try the CLTS or COTS loopback transport */ + kcp->client = clnt_tp_create(u.nodename, + KEY_PROG, vers, tpconf); + endnetconfig(localhandle); if (kcp->client == (CLIENT *) NULL) { return ((CLIENT *) NULL); @@ -364,8 +398,8 @@ getkeyserv_handle(int vers) /* returns 0 on failure, 1 on success */ static int -key_call(u_long proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, - char *rslt) +key_call(u_long proc, xdrproc_t xdr_arg, void *arg, xdrproc_t xdr_rslt, + void *rslt) { CLIENT *clnt; struct timeval wait_time; diff --git a/lib/libc/rpc/key_prot_xdr.c b/lib/libc/rpc/key_prot_xdr.c index 14a4c99aca..f3663aeeaa 100644 --- a/lib/libc/rpc/key_prot_xdr.c +++ b/lib/libc/rpc/key_prot_xdr.c @@ -114,12 +114,14 @@ xdr_cryptkeyres(XDR *xdrs, cryptkeyres *objp) bool_t xdr_unixcred(XDR *xdrs, unixcred *objp) { + u_int **pgids_val; if (!xdr_u_int(xdrs, &objp->uid)) return (FALSE); if (!xdr_u_int(xdrs, &objp->gid)) return (FALSE); - if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS, + pgids_val = &objp->gids.gids_val; + if (!xdr_array(xdrs, (char **) pgids_val, (u_int *) &objp->gids.gids_len, MAXGIDS, sizeof (u_int), (xdrproc_t) xdr_u_int)) return (FALSE); return (TRUE); diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c new file mode 100644 index 0000000000..54eb4b83c0 --- /dev/null +++ b/lib/libc/rpc/mt_misc.c @@ -0,0 +1,117 @@ +/* @(#)mt_misc.c 1.24 93/04/29 SMI */ +/* $NetBSD: mt_misc.c,v 1.1 2000/06/02 23:11:11 fvdl Exp $ */ +/* $FreeBSD: src/lib/libc/rpc/mt_misc.c,v 1.7 2006/02/27 22:10:59 deischen Exp $ */ +/* $DragonFly$ */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include "un-namespace.h" +#include "mt_misc.h" + +/* Take these objects out of the application namespace. */ +#define svc_lock __svc_lock +#define svc_fd_lock __svc_fd_lock +#define rpcbaddr_cache_lock __rpcbaddr_cache_lock +#define authdes_ops_lock __authdes_ops_lock +#define authnone_lock __authnone_lock +#define authsvc_lock __authsvc_lock +#define clnt_fd_lock __clnt_fd_lock +#define clntraw_lock __clntraw_lock +#define dupreq_lock __dupreq_lock +#define loopnconf_lock __loopnconf_lock +#define ops_lock __ops_lock +#define proglst_lock __proglst_lock +#define rpcsoc_lock __rpcsoc_lock +#define svcraw_lock __svcraw_lock +#define tsd_lock __tsd_lock +#define xprtlist_lock __xprtlist_lock + +/* 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; + +/* 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; + +/* 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; + +/* dupreq variables (svc_dg.c) */ +pthread_mutex_t dupreq_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 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; + +/* xprtlist (svc_generic.c) */ +pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER; + +#undef rpc_createerr + +struct rpc_createerr rpc_createerr; + +struct rpc_createerr * +__rpc_createerr(void) +{ + 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/mt_misc.h b/lib/libc/rpc/mt_misc.h new file mode 100644 index 0000000000..3d70175dc4 --- /dev/null +++ b/lib/libc/rpc/mt_misc.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2006 The FreeBSD Project. 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 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 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: src/lib/libc/rpc/mt_misc.h,v 1.2 2006/02/28 07:36:25 delphij Exp $ + * $DragonFly$ + */ +#ifndef _MT_MISC_H +#define _MT_MISC_H + +/* Take these locks out of the application namespace. */ +#define svc_lock __svc_lock +#define svc_fd_lock __svc_fd_lock +#define rpcbaddr_cache_lock __rpcbaddr_cache_lock +#define authdes_ops_lock __authdes_ops_lock +#define authnone_lock __authnone_lock +#define authsvc_lock __authsvc_lock +#define clnt_fd_lock __clnt_fd_lock +#define clntraw_lock __clntraw_lock +#define dupreq_lock __dupreq_lock +#define loopnconf_lock __loopnconf_lock +#define ops_lock __ops_lock +#define proglst_lock __proglst_lock +#define rpcsoc_lock __rpcsoc_lock +#define svcraw_lock __svcraw_lock +#define tsd_lock __tsd_lock +#define xprtlist_lock __xprtlist_lock + +extern pthread_rwlock_t svc_lock; +extern pthread_rwlock_t svc_fd_lock; +extern pthread_rwlock_t rpcbaddr_cache_lock; +extern pthread_mutex_t authdes_ops_lock; +extern pthread_mutex_t svcauthdesstats_lock; +extern pthread_mutex_t authnone_lock; +extern pthread_mutex_t authsvc_lock; +extern pthread_mutex_t clnt_fd_lock; +extern pthread_mutex_t clntraw_lock; +extern pthread_mutex_t dupreq_lock; +extern pthread_mutex_t loopnconf_lock; +extern pthread_mutex_t ops_lock; +extern pthread_mutex_t proglst_lock; +extern pthread_mutex_t rpcsoc_lock; +extern pthread_mutex_t svcraw_lock; +extern pthread_mutex_t tsd_lock; +extern pthread_mutex_t xprtlist_lock; + +#endif diff --git a/lib/libc/rpc/netconfig.5 b/lib/libc/rpc/netconfig.5 new file mode 100644 index 0000000000..9ab3c78118 --- /dev/null +++ b/lib/libc/rpc/netconfig.5 @@ -0,0 +1,132 @@ +.\" $NetBSD: netconfig.5,v 1.2 2000/11/08 13:18:28 lukem Exp $ +.\" $FreeBSD: src/lib/libc/rpc/netconfig.5,v 1.3 2006/01/11 13:57:15 ceri Exp $ +.\" $DragonFly$ +.Dd November 15, 2008 +.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 one or more of the following characters: +.Bl -tag -width b -offset indent +.It Sy b +The network represented by this entry is broadcast capable. +This flag is meaningless in +.Fx . +.It Sy v +The entry may be returned by the +.Xr getnetpath 3 +function. +.El +.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 */ + unsigned long nc_flag; /* Flags */ + 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 456465288e..5cef0e8cf8 100644 --- a/lib/libc/rpc/netname.c +++ b/lib/libc/rpc/netname.c @@ -27,7 +27,7 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * $FreeBSD: src/lib/libc/rpc/netname.c,v 1.2.6.1 2000/08/23 00:05:29 jhb Exp $ + * $FreeBSD: src/lib/libc/rpc/netname.c,v 1.8 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/netname.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ * * @(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro @@ -41,6 +41,7 @@ * the sun NIS domain architecture. */ +#include "namespace.h" #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include "un-namespace.h" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 @@ -98,12 +100,12 @@ getnetname(char *name) * Convert unix cred to network-name */ int -user2netname(char *netname, uid_t uid, char *domain) +user2netname(char *netname, const uid_t uid, const char *domain) { char *dfltdom; if (domain == NULL) { - if (_rpc_get_default_domain(&dfltdom) != 0) { + if (__rpc_get_default_domain(&dfltdom) != 0) { return (0); } domain = dfltdom; @@ -120,13 +122,13 @@ user2netname(char *netname, uid_t uid, char *domain) * Convert host to network-name */ int -host2netname(char *netname, char *host, char *domain) +host2netname(char *netname, const char *host, const char *domain) { char *dfltdom; char hostname[MAXHOSTNAMELEN+1]; if (domain == NULL) { - if (_rpc_get_default_domain(&dfltdom) != 0) { + if (__rpc_get_default_domain(&dfltdom) != 0) { return (0); } domain = dfltdom; diff --git a/lib/libc/rpc/netnamer.c b/lib/libc/rpc/netnamer.c index 4396918480..90d1c168f7 100644 --- a/lib/libc/rpc/netnamer.c +++ b/lib/libc/rpc/netnamer.c @@ -27,17 +27,19 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * $FreeBSD: src/lib/libc/rpc/netnamer.c,v 1.3.6.1 2000/09/20 04:43:11 jkh Exp $ + * $FreeBSD: src/lib/libc/rpc/netnamer.c,v 1.12 2005/03/10 00:58:21 stefanf Exp $ * $DragonFly: src/lib/libc/rpc/netnamer.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ * * @(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro */ + /* * netname utility routines convert from unix names to network names and * vice-versa This module is operating system dependent! What we define here * will work with any unix system that has adopted the sun NIS domain * architecture. */ +#include "namespace.h" #include #include #include @@ -52,13 +54,16 @@ #include #include #include +#include "un-namespace.h" static char *OPSYS = "unix"; +#ifdef YP static char *NETID = "netid.byname"; +#endif static char *NETIDFILE = "/etc/netid"; -static int getnetid ( char *, char * ); -static int _getgroups ( char *, gid_t * ); +static int _getgroups(char *, gid_t *); +static int getnetid(char *, char *); #ifndef NGROUPS #define NGROUPS 16 @@ -94,7 +99,6 @@ netname2user(char *netname, uid_t *uidp, gid_t *gidp, int *gidlenp, return (0); } *gidp = (gid_t) atol(p); - gidlen = 0; for (gidlen = 0; gidlen < NGROUPS; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) @@ -120,7 +124,7 @@ netname2user(char *netname, uid_t *uidp, gid_t *gidp, int *gidlenp, strncpy(val, val1, 1024); val[vallen] = 0; - err = _rpc_get_default_domain(&domain); /* change to rpc */ + err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); @@ -216,7 +220,7 @@ netname2host(char *netname, char *hostname, int hostlen) strncpy(hostname, val, vallen); hostname[vallen] = 0; - err = _rpc_get_default_domain(&domain); /* change to rpc */ + err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); diff --git a/lib/libc/rpc/pmap_clnt.c b/lib/libc/rpc/pmap_clnt.c index dacaebb413..a220cffb20 100644 --- a/lib/libc/rpc/pmap_clnt.c +++ b/lib/libc/rpc/pmap_clnt.c @@ -28,7 +28,8 @@ * * @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro * @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_clnt.c,v 1.11 2000/01/27 23:06:39 jasone Exp $ + * $NetBSD: pmap_clnt.c,v 1.16 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_clnt.c,v 1.15 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_clnt.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ @@ -43,102 +44,74 @@ #include #include #include + #include #include #include +#include #include #include "un-namespace.h" -static struct timeval timeout = { 5, 0 }; -static struct timeval tottimeout = { 60, 0 }; - -void clnt_perror(); +#include +#include -#ifndef PORTMAPSOCK -#define PORTMAPSOCK "/var/run/portmapsock" -#endif +#include "rpc_com.h" -/* - * Set a mapping between program,version and port. - * Calls the pmap service remotely to do the mapping. - */ bool_t pmap_set(u_long program, u_long version, int protocol, u_short port) { - struct sockaddr_in myaddress; - int socket = -1; - 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) - _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(u_long program, u_long version) { - struct sockaddr_in myaddress; - int socket = -1; - 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) - _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 f618a31836..087070a4af 100644 --- a/lib/libc/rpc/pmap_getmaps.c +++ b/lib/libc/rpc/pmap_getmaps.c @@ -28,7 +28,8 @@ * * @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro * @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_getmaps.c,v 1.11 2000/01/27 23:06:39 jasone Exp $ + * $NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_getmaps.c,v 1.16 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_getmaps.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ @@ -41,16 +42,22 @@ */ #include "namespace.h" -#include -#include -#include +#include #include +#include + +#include +#include + +#include +#include #include #include #include -#include -#include -#include + +#include +#include +#include #include "un-namespace.h" #define NAMELEN 255 @@ -63,25 +70,27 @@ struct pmaplist * pmap_getmaps(struct sockaddr_in *address) { - struct pmaplist *head = (struct pmaplist *)NULL; - int socket = -1; + struct pmaplist *head = NULL; + int sock = -1; struct timeval minutetimeout; CLIENT *client; + assert(address != NULL); + minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; address->sin_port = htons(PMAPPORT); client = clnttcp_create(address, PMAPPROG, - PMAPVERS, &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) - _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 71346db902..e6aa9bfdd3 100644 --- a/lib/libc/rpc/pmap_getport.c +++ b/lib/libc/rpc/pmap_getport.c @@ -28,7 +28,8 @@ * * @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro * @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_getport.c,v 1.10 2000/01/27 23:06:40 jasone Exp $ + * $NetBSD: pmap_getport.c,v 1.16 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_getport.c,v 1.15 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_getport.c,v 1.6 2005/11/13 12:27:04 swildner Exp $ */ @@ -40,28 +41,22 @@ */ #include "namespace.h" -#include -#include -#include +#include #include + +#include #include + +#include #include -#include "un-namespace.h" -static struct timeval timeout = { 5, 0 }; -static struct timeval tottimeout = { 60, 0 }; +#include +#include +#include +#include "un-namespace.h" -/* - * Change the primary pmap_getport() timeout - */ -void -pmap_getport_timeout(struct timeval *otv, struct timeval *ntv) -{ - if (otv) - *otv = tottimeout; - if (ntv) - tottimeout = *ntv; -} +static const struct timeval timeout = { 5, 0 }; +static const struct timeval tottimeout = { 60, 0 }; /* * Find the mapped port for program,version. @@ -73,20 +68,24 @@ pmap_getport(struct sockaddr_in *address, u_long program, u_long version, u_int protocol) { u_short port = 0; - int socket = -1; + 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) { @@ -94,8 +93,6 @@ pmap_getport(struct sockaddr_in *address, u_long program, u_long version, } CLNT_DESTROY(client); } - if (socket != -1) - _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 0ab4da6189..bb6a43d32f 100644 --- a/lib/libc/rpc/pmap_prot.c +++ b/lib/libc/rpc/pmap_prot.c @@ -28,7 +28,8 @@ * * @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro * @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_prot.c,v 1.6 1999/08/28 00:00:42 peter Exp $ + * $NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_prot.c,v 1.9 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_prot.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ */ @@ -39,15 +40,22 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include + #include #include #include +#include "un-namespace.h" bool_t xdr_pmap(XDR *xdrs, struct pmap *regs) { + assert(xdrs != NULL); + assert(regs != NULL); + if (xdr_u_long(xdrs, ®s->pm_prog) && xdr_u_long(xdrs, ®s->pm_vers) && xdr_u_long(xdrs, ®s->pm_prot)) diff --git a/lib/libc/rpc/pmap_prot2.c b/lib/libc/rpc/pmap_prot2.c index a7df93b104..153becf255 100644 --- a/lib/libc/rpc/pmap_prot2.c +++ b/lib/libc/rpc/pmap_prot2.c @@ -28,7 +28,8 @@ * * @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro * @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_prot2.c,v 1.7 1999/08/28 00:00:42 peter Exp $ + * $NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_prot2.c,v 1.10 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_prot2.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -39,9 +40,13 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include + #include #include #include +#include "un-namespace.h" /* @@ -91,10 +96,15 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp) * xdr_bool when the direction is XDR_DECODE. */ bool_t more_elements; - int freeing = (xdrs->x_op == XDR_FREE); - struct pmaplist **next = NULL; + int freeing; + struct pmaplist **next = NULL; /* pacify gcc */ + + assert(xdrs != NULL); + assert(rp != NULL); + + freeing = (xdrs->x_op == XDR_FREE); - while (TRUE) { + for (;;) { more_elements = (bool_t)(*rp != NULL); if (! xdr_bool(xdrs, &more_elements)) return (FALSE); @@ -108,8 +118,19 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp) if (freeing) 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(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 e8ae0b2b08..5b59abf9dc 100644 --- a/lib/libc/rpc/pmap_rmt.c +++ b/lib/libc/rpc/pmap_rmt.c @@ -28,7 +28,8 @@ * * @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro * @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/pmap_rmt.c,v 1.16.2.1 2002/06/30 23:34:58 iedowse Exp $ + * $NetBSD: pmap_rmt.c,v 1.29 2000/07/06 03:10:34 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/pmap_rmt.c,v 1.20 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/pmap_rmt.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ @@ -41,24 +42,29 @@ */ #include "namespace.h" +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #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. @@ -72,15 +78,18 @@ pmap_rmtcall(struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, struct timeval tout, u_long *port_ptr) { - int socket = -1; + 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; @@ -89,14 +98,13 @@ pmap_rmtcall(struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, 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) - _close(socket); addr->sin_port = 0; return (stat); } @@ -111,6 +119,9 @@ xdr_rmtcall_args(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))) { @@ -140,272 +151,14 @@ xdr_rmtcallres(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(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(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; - XDR *xdrs = &xdr_stream; - int outlen, inlen, fromlen, nets; - int sock; - int on = 1; - fd_set *fds, readfds; - int i; - bool_t done = FALSE; - 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); - 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) { - int success = 0; - for (i = 0; i < nets; i++) { - baddr.sin_addr = addrs[i]; - if (_sendto(sock, outbuf, outlen, 0, - (struct sockaddr *)&baddr, - sizeof (struct sockaddr)) == outlen) { - success++; - } - } - if (!success) { - 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; - xdr_replymsg(xdrs, &msg); - (*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) - _close(sock); - AUTH_DESTROY(unix_auth); - return (stat); -} - diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3 index 5450746dc1..0a92a3690e 100644 --- a/lib/libc/rpc/rpc.3 +++ b/lib/libc/rpc/rpc.3 @@ -1,1522 +1,519 @@ -.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI -.\" $FreeBSD: src/lib/libc/rpc/rpc.3,v 1.11.2.5 2001/12/14 18:33:56 ru Exp $ +.\" @(#)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: src/lib/libc/rpc/rpc.3,v 1.23 2004/07/03 22:30:09 ru Exp $ .\" $DragonFly: src/lib/libc/rpc/rpc.3,v 1.8 2008/05/01 22:06:06 swildner Exp $ .\" -.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 .In rpc/rpc.h -.Pp -See -.Sx DESCRIPTION -for function declarations. +.In 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. -.Pp -.Bl -tag -width indent -compact -.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 -.Ft int -.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 "const char *host" "u_long prog" "u_long vers" "const 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 -.It Dv CLSET_CONNECT Ta Vt "int" Ta use Xr connect 2 -.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 "const 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 +.In rpc/rpc.h . +Routines that take a +.Vt "struct netconfig" +also require that +.In netconfig.h +be included. +.Sh Nettype +Some of the high-level +RPC interface routines take a +.Fa nettype +string as one of the arguments +(for example, .Fn clnt_create , -.Fn clntraw_create , -.Fn clnttcp_create , -or -.Fn clntudp_create -call fails. +.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 -.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" "const 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 "const 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_spcreateerror , -.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" "const 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 +.Fa nettype +argument +can be one of the following: +.Bl -tag -width datagram_v +.It netpath +Choose from the transports which have been +indicated by their token names in the +.Ev NETPATH +environment variable. +.Ev NETPATH +is unset or +.Dv NULL , +it defaults to +.Qq visible . +.Qq netpath +is the default +.Fa nettype . +.It visible +Choose the transports which have the visible flag (v) +set in the +.Pa /etc/netconfig +file. +.It circuit_v +This is same as +.Qq visible +except that it chooses only the connection oriented transports +(semantics +.Qq tpi_cots or -.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 */ + u_int x_handy; /* extra private word */ +} XDR; + +/* + * The netbuf structure. This structure is defined in on SysV + * systems, but NetBSD / FreeBSD do not use XTI. + * + * Usually, buf will point to a struct sockaddr, and len and maxlen + * will contain the length and maximum length of that socket address, + * respectively. + */ +struct netbuf { + unsigned int maxlen; + unsigned int len; + void *buf; +}; + +/* + * The format of the address and options arguments of the XTI t_bind call. + * Only provided for compatibility, it should not be used other than + * as an argument to svc_tli_create(). + */ + +struct t_bind { + struct netbuf addr; + unsigned int qlen; +}; +.Ed +.Sh "Index to Routines" +The following table lists RPC routines and the manual reference +pages on which they are described: +.Pp +.Bl -tag -width "authunix_create_default()" -compact +.It Em "RPC Routine" +.Em "Manual Reference Page" +.Pp +.It Fn auth_destroy +.Xr rpc_clnt_auth 3 +.It Fn authdes_create +.Xr rpc_soc 3 +.It Fn authnone_create +.Xr rpc_clnt_auth 3 +.It Fn authsys_create +.Xr rpc_clnt_auth 3 +.It Fn authsys_create_default +.Xr rpc_clnt_auth 3 +.It Fn authunix_create +.Xr rpc_soc 3 +.It Fn authunix_create_default +.Xr rpc_soc 3 +.It Fn callrpc +.Xr rpc_soc 3 +.It Fn clnt_broadcast +.Xr rpc_soc 3 +.It Fn clnt_call +.Xr rpc_clnt_calls 3 +.It Fn clnt_control +.Xr rpc_clnt_create 3 +.It Fn clnt_create +.Xr rpc_clnt_create 3 +.It Fn clnt_create_timed +.Xr rpc_clnt_create 3 +.It Fn clnt_create_vers +.Xr rpc_clnt_create 3 +.It Fn clnt_create_vers_timed +.Xr rpc_clnt_create 3 +.It Fn clnt_destroy +.Xr rpc_clnt_create 3 +.It Fn clnt_dg_create +.Xr rpc_clnt_create 3 +.It Fn clnt_freeres +.Xr rpc_clnt_calls 3 +.It Fn clnt_geterr +.Xr rpc_clnt_calls 3 +.It Fn clnt_pcreateerror +.Xr rpc_clnt_create 3 +.It Fn clnt_perrno +.Xr rpc_clnt_calls 3 +.It Fn clnt_perror +.Xr rpc_clnt_calls 3 +.It Fn clnt_raw_create +.Xr rpc_clnt_create 3 +.It Fn clnt_spcreateerror +.Xr rpc_clnt_create 3 +.It Fn clnt_sperrno +.Xr rpc_clnt_calls 3 +.It Fn clnt_sperror +.Xr rpc_clnt_calls 3 +.It Fn clnt_tli_create +.Xr rpc_clnt_create 3 +.It Fn clnt_tp_create +.Xr rpc_clnt_create 3 +.It Fn clnt_tp_create_timed +.Xr rpc_clnt_create 3 +.It Fn clnt_udpcreate +.Xr rpc_soc 3 +.It Fn clnt_vc_create +.Xr rpc_clnt_create 3 +.It Fn clntraw_create +.Xr rpc_soc 3 +.It Fn clnttcp_create +.Xr rpc_soc 3 +.It Fn clntudp_bufcreate +.Xr rpc_soc 3 +.It Fn get_myaddress +.Xr rpc_soc 3 +.It Fn pmap_getmaps +.Xr rpc_soc 3 +.It Fn pmap_getport +.Xr rpc_soc 3 +.It Fn pmap_rmtcall +.Xr rpc_soc 3 +.It Fn pmap_set +.Xr rpc_soc 3 +.It Fn pmap_unset +.Xr rpc_soc 3 +.It Fn registerrpc +.Xr rpc_soc 3 +.It Fn rpc_broadcast +.Xr rpc_clnt_calls 3 +.It Fn rpc_broadcast_exp +.Xr rpc_clnt_calls 3 +.It Fn rpc_call +.Xr rpc_clnt_calls 3 +.It Fn rpc_reg +.Xr rpc_svc_calls 3 +.It Fn svc_create +.Xr rpc_svc_create 3 +.It Fn svc_destroy +.Xr rpc_svc_create 3 +.It Fn svc_dg_create +.Xr rpc_svc_create 3 +.It Fn svc_dg_enablecache +.Xr rpc_svc_calls 3 +.It Fn svc_fd_create +.Xr rpc_svc_create 3 +.It Fn svc_fds +.Xr rpc_soc 3 +.It Fn svc_freeargs +.Xr rpc_svc_reg 3 +.It Fn svc_getargs +.Xr rpc_svc_reg 3 +.It Fn svc_getcaller +.Xr rpc_soc 3 +.It Fn svc_getreq +.Xr rpc_soc 3 +.It Fn svc_getreqset +.Xr rpc_svc_calls 3 +.It Fn svc_getrpccaller +.Xr rpc_svc_calls 3 +.It Fn svc_kerb_reg +.Xr kerberos_rpc 3 +.It Fn svc_raw_create +.Xr rpc_svc_create 3 +.It Fn svc_reg +.Xr rpc_svc_calls 3 +.It Fn svc_register +.Xr rpc_soc 3 +.It Fn svc_run +.Xr rpc_svc_reg 3 +.It Fn svc_sendreply +.Xr rpc_svc_reg 3 +.It Fn svc_tli_create +.Xr rpc_svc_create 3 +.It Fn svc_tp_create +.Xr rpc_svc_create 3 +.It Fn svc_unreg +.Xr rpc_svc_calls 3 +.It Fn svc_unregister +.Xr rpc_soc 3 +.It Fn svc_vc_create +.Xr rpc_svc_create 3 +.It Fn svcerr_auth +.Xr rpc_svc_err 3 +.It Fn svcerr_decode +.Xr rpc_svc_err 3 +.It Fn svcerr_noproc +.Xr rpc_svc_err 3 +.It Fn svcerr_noprog +.Xr rpc_svc_err 3 +.It Fn svcerr_progvers +.Xr rpc_svc_err 3 +.It Fn svcerr_systemerr +.Xr rpc_svc_err 3 +.It Fn svcerr_weakauth +.Xr rpc_svc_err 3 +.It Fn svcfd_create +.Xr rpc_soc 3 +.It Fn svcraw_create +.Xr rpc_soc 3 +.It Fn svctcp_create +.Xr rpc_soc 3 +.It Fn svcudp_bufcreate +.Xr rpc_soc 3 +.It Fn svcudp_create +.Xr rpc_soc 3 +.It Fn xdr_accepted_reply +.Xr rpc_xdr 3 +.It Fn xdr_authsys_parms +.Xr rpc_xdr 3 +.It Fn xdr_authunix_parms +.Xr rpc_soc 3 +.It Fn xdr_callhdr +.Xr rpc_xdr 3 +.It Fn xdr_callmsg +.Xr rpc_xdr 3 +.It Fn xdr_opaque_auth +.Xr rpc_xdr 3 +.It Fn xdr_rejected_reply +.Xr rpc_xdr 3 +.It Fn xdr_replymsg +.Xr rpc_xdr 3 +.It Fn xprt_register +.Xr rpc_svc_calls 3 +.It Fn xprt_unregister +.Xr rpc_svc_calls 3 +.El +.Sh FILES +.Bl -tag -width /etc/netconfig +.It Pa /etc/netconfig .El .Sh SEE ALSO -.Xr 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 RFC 1050 -.%Q "Sun Microsystems, Inc., USC-ISI" -.Re +.Xr getnetconfig 3 , +.Xr getnetpath 3 , +.Xr rpcbind 3 , +.Xr rpc_clnt_auth 3 , +.Xr rpc_clnt_calls 3 , +.Xr rpc_clnt_create 3 , +.Xr rpc_svc_calls 3 , +.Xr rpc_svc_create 3 , +.Xr rpc_svc_err 3 , +.Xr rpc_svc_reg 3 , +.Xr rpc_xdr 3 , +.Xr xdr 3 , +.Xr netconfig 5 diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5 index 810468ad61..1517d5dae2 100644 --- a/lib/libc/rpc/rpc.5 +++ b/lib/libc/rpc/rpc.5 @@ -1,37 +1,60 @@ -.\" $FreeBSD: src/lib/libc/rpc/rpc.5,v 1.6.2.2 2000/12/29 14:44:49 ru Exp $ +.\" $NetBSD: rpc.5,v 1.3 2000/06/15 20:05:54 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc.5,v 1.11 2005/01/20 09:17:04 ru Exp $ .\" $DragonFly: src/lib/libc/rpc/rpc.5,v 1.2 2003/06/17 04:26:45 dillon Exp $ -.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI; -.Dd September 26, 1985 +.\" @(#)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 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 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 SEE ALSO .Xr getrpcent 3 diff --git a/lib/libc/rpc/rpc_callmsg.c b/lib/libc/rpc/rpc_callmsg.c index 969e3b57e0..1177a9fc60 100644 --- a/lib/libc/rpc/rpc_callmsg.c +++ b/lib/libc/rpc/rpc_callmsg.c @@ -28,7 +28,8 @@ * * @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro * @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/rpc_callmsg.c,v 1.9 1999/08/28 00:00:45 peter Exp $ + * $NetBSD: rpc_callmsg.c,v 1.16 2000/07/14 08:40:42 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_callmsg.c,v 1.13 2007/11/20 01:51:20 jb Exp $ * $DragonFly: src/lib/libc/rpc/rpc_callmsg.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -39,10 +40,13 @@ * */ -#include +#include "namespace.h" +#include #include #include + #include +#include "un-namespace.h" /* * XDR a call message @@ -50,9 +54,13 @@ bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) { + enum msg_type *prm_direction; int32_t *buf; struct opaque_auth *oa; + assert(xdrs != NULL); + assert(cmsg != NULL); + if (xdrs->x_op == XDR_ENCODE) { if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { return (FALSE); @@ -65,30 +73,30 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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); */ @@ -99,28 +107,30 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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) { @@ -129,7 +139,7 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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) / @@ -146,7 +156,7 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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) { @@ -154,7 +164,9 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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) { @@ -163,7 +175,7 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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) / @@ -174,9 +186,10 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg) return (TRUE); } } + prm_direction = &cmsg->rm_direction; if ( xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && - xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + xdr_enum(xdrs, (enum_t *) prm_direction) && (cmsg->rm_direction == CALL) && xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && @@ -184,7 +197,6 @@ xdr_callmsg(XDR *xdrs, struct rpc_msg *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 0000000000..0ac68b908f --- /dev/null +++ b/lib/libc/rpc/rpc_clnt_auth.3 @@ -0,0 +1,97 @@ +.\" @(#)rpc_clnt_auth.3n 1.21 93/05/07 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_clnt_auth 1.4 89/07/20 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $NetBSD: rpc_clnt_auth.3,v 1.1 2000/06/03 09:29:50 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_auth.3,v 1.6 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 7, 1993 +.Dt RPC_CLNT_AUTH 3 +.Os +.Sh NAME +.Nm auth_destroy , +.Nm authnone_create , +.Nm authsys_create , +.Nm authsys_create_default +.Nd library routines for client side remote procedure call authentication +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft "void" +.Fn auth_destroy "AUTH *auth" +.Ft "AUTH *" +.Fn authnone_create "void" +.Ft "AUTH *" +.Fn authsys_create "const char *host" "const uid_t uid" "const gid_t gid" "const int len" "const gid_t *aup_gids" +.Ft "AUTH *" +.Fn authsys_create_default "void" +.Sh DESCRIPTION +These routines are part of the +RPC library that allows C language programs to make procedure +calls on other machines across the network, +with desired authentication. +.Pp +These routines are normally called after creating the +.Vt CLIENT +handle. +The +.Va cl_auth +field of the +.Vt CLIENT +structure should be initialized by the +.Vt AUTH +structure returned by some of the following routines. +The client's authentication information +is passed to the server when the +RPC +call is made. +.Pp +Only the +.Dv NULL +and the +.Dv SYS +style of authentication is discussed here. +.Sh Routines +.Bl -tag -width authsys_create_default() +.It Fn auth_destroy +A function macro that destroys the authentication +information associated with +.Fa auth . +Destruction usually involves deallocation +of private data structures. +The use of +.Fa auth +is undefined after calling +.Fn auth_destroy . +.It Fn authnone_create +Create and return an RPC +authentication handle that passes nonusable +authentication information with each remote procedure call. +This is the default authentication used by RPC. +.It Fn authsys_create +Create and return an RPC authentication handle that contains +.Dv AUTH_SYS +authentication information. +The +.Fa host +argument +is the name of the machine on which the information was +created; +.Fa uid +is the user's user ID; +.Fa gid +is the user's current group ID; +.Fa len +and +.Fa aup_gids +refer to a counted array of groups to which the user belongs. +.It Fn authsys_create_default +Call +.Fn authsys_create +with the appropriate arguments. +.El +.Sh SEE ALSO +.Xr rpc 3 , +.Xr rpc_clnt_calls 3 , +.Xr rpc_clnt_create 3 diff --git a/lib/libc/rpc/rpc_clnt_calls.3 b/lib/libc/rpc/rpc_clnt_calls.3 new file mode 100644 index 0000000000..6f37922b0e --- /dev/null +++ b/lib/libc/rpc/rpc_clnt_calls.3 @@ -0,0 +1,317 @@ +.\" @(#)rpc_clnt_calls.3n 1.30 93/08/31 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_clnt_calls 1.4 89/07/20 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_calls.3,v 1.8 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 7, 1993 +.Dt RPC_CLNT_CALLS 3 +.Os +.Sh NAME +.Nm rpc_clnt_calls , +.Nm clnt_call , +.Nm clnt_freeres , +.Nm clnt_geterr , +.Nm clnt_perrno , +.Nm clnt_perror , +.Nm clnt_sperrno , +.Nm clnt_sperror , +.Nm rpc_broadcast , +.Nm rpc_broadcast_exp , +.Nm rpc_call +.Nd library routines for client side calls +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft "enum clnt_stat" +.Fn clnt_call "CLIENT *clnt" "const rpcproc_t procnum" "const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "caddr_t out" "const struct timeval tout" +.Ft bool_t +.Fn clnt_freeres "CLIENT *clnt" "const xdrproc_t outproc" "caddr_t out" +.Ft void +.Fn clnt_geterr "const CLIENT * clnt" "struct rpc_err * errp" +.Ft void +.Fn clnt_perrno "const enum clnt_stat stat" +.Ft void +.Fn clnt_perror "CLIENT *clnt" "const char *s" +.Ft "char *" +.Fn clnt_sperrno "const enum clnt_stat stat" +.Ft "char *" +.Fn clnt_sperror "CLIENT *clnt" "const char * s" +.Ft "enum clnt_stat" +.Fo rpc_broadcast +.Fa "const rpcprog_t prognum" "const rpcvers_t versnum" +.Fa "const rpcproc_t procnum" "const xdrproc_t inproc" +.Fa "const caddr_t in" "const xdrproc_t outproc" "caddr_t out" +.Fa "const resultproc_t eachresult" "const char *nettype" +.Fc +.Ft "enum clnt_stat" +.Fo rpc_broadcast_exp +.Fa "const rpcprog_t prognum" "const rpcvers_t versnum" +.Fa "const rpcproc_t procnum" "const xdrproc_t xargs" +.Fa "caddr_t argsp" "const xdrproc_t xresults" +.Fa "caddr_t resultsp" "const resultproc_t eachresult" +.Fa "const int inittime" "const int waittime" +.Fa "const char * nettype" +.Fc +.Ft "enum clnt_stat" +.Fo rpc_call +.Fa "const char *host" "const rpcprog_t prognum" +.Fa "const rpcvers_t versnum" "const rpcproc_t procnum" +.Fa "const xdrproc_t inproc" "const char *in" +.Fa "const xdrproc_t outproc" "char *out" "const char *nettype" +.Fc +.Sh DESCRIPTION +RPC library routines allow C language programs to make procedure +calls on other machines across the network. +First, the client calls a procedure to send a request to the server. +Upon receipt of the request, the server calls a dispatch routine +to perform the requested service, and then sends back a reply. +.Pp +The +.Fn clnt_call , +.Fn rpc_call , +and +.Fn rpc_broadcast +routines handle the client side of the procedure call. +The remaining routines deal with error handling in the case of errors. +.Pp +Some of the routines take a +.Vt CLIENT +handle as one of the arguments. +A +.Vt CLIENT +handle can be created by an RPC creation routine such as +.Fn clnt_create +(see +.Xr rpc_clnt_create 3 ) . +.Pp +These routines are safe for use in multithreaded applications. +.Vt CLIENT +handles can be shared between threads, however in this implementation +requests by different threads are serialized (that is, the first request will +receive its results before the second request is sent). +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt CLIENT +data structure. +.Bl -tag -width XXXXX +.It Fn clnt_call +A function macro that calls the remote procedure +.Fa procnum +associated with the client handle, +.Fa clnt , +which is obtained with an RPC +client creation routine such as +.Fn clnt_create +(see +.Xr rpc_clnt_create 3 ) . +The +.Fa inproc +argument +is the XDR function used to encode the procedure's arguments, and +.Fa outproc +is the XDR function used to decode the procedure's results; +.Fa in +is the address of the procedure's argument(s), and +.Fa out +is the address of where to place the result(s). +The +.Fa tout +argument +is the time allowed for results to be returned, which is overridden by +a time-out set explicitly through +.Fn clnt_control , +see +.Xr rpc_clnt_create 3 . +If the remote call succeeds, the status returned is +.Dv RPC_SUCCESS , +otherwise an appropriate status is returned. +.It Fn clnt_freeres +A function macro that frees any data allocated by the +RPC/XDR system when it decoded the results of an RPC call. +The +.Fa out +argument +is the address of the results, and +.Fa outproc +is the XDR routine describing the results. +This routine returns 1 if the results were successfully freed, +and 0 otherwise. +.It Fn clnt_geterr +A function macro that copies the error structure out of the client +handle to the structure at address +.Fa errp . +.It Fn clnt_perrno +Print a message to standard error corresponding +to the condition indicated by +.Fa stat . +A newline is appended. +Normally used after a procedure call fails for a routine +for which a client handle is not needed, for instance +.Fn rpc_call . +.It Fn clnt_perror +Print a message to the standard error indicating why an +RPC call failed; +.Fa clnt +is the handle used to do the call. +The message is prepended with string +.Fa s +and a colon. +A newline is appended. +Normally used after a remote procedure call fails +for a routine which requires a client handle, +for instance +.Fn clnt_call . +.It Fn clnt_sperrno +Take the same arguments as +.Fn clnt_perrno , +but instead of sending a message to the standard error +indicating why an RPC +call failed, return a pointer to a string which contains the message. +The +.Fn clnt_sperrno +function +is normally used instead of +.Fn clnt_perrno +when the program does not have a standard error (as a program +running as a server quite likely does not), or if the programmer +does not want the message to be output with +.Fn printf +(see +.Xr printf 3 ) , +or if a message format different than that supported by +.Fn clnt_perrno +is to be used. +Note: +unlike +.Fn clnt_sperror +and +.Fn clnt_spcreateerror +(see +.Xr rpc_clnt_create 3 ) , +.Fn clnt_sperrno +does not return pointer to static data so the +result will not get overwritten on each call. +.It Fn clnt_sperror +Like +.Fn clnt_perror , +except that (like +.Fn clnt_sperrno ) +it returns a string instead of printing to standard error. +However, +.Fn clnt_sperror +does not append a newline at the end of the message. +Warning: +returns pointer to a buffer that is overwritten +on each call. +.It Fn rpc_broadcast +Like +.Fn rpc_call , +except the call message is broadcast to +all the connectionless transports specified by +.Fa nettype . +If +.Fa nettype +is +.Dv NULL , +it defaults to +.Qq netpath . +Each time it receives a response, +this routine calls +.Fn eachresult , +whose form is: +.Ft bool_t +.Fn eachresult "caddr_t out" "const struct netbuf * addr" "const struct netconfig * netconf" +where +.Fa out +is the same as +.Fa out +passed to +.Fn rpc_broadcast , +except that the remote procedure's output is decoded there; +.Fa addr +points to the address of the machine that sent the results, and +.Fa netconf +is the netconfig structure of the transport on which the remote +server responded. +If +.Fn eachresult +returns 0, +.Fn rpc_broadcast +waits for more replies; +otherwise it returns with appropriate status. +Warning: +broadcast file descriptors are limited in size to the +maximum transfer size of that transport. +For Ethernet, this value is 1500 bytes. +The +.Fn rpc_broadcast +function +uses +.Dv AUTH_SYS +credentials by default (see +.Xr rpc_clnt_auth 3 ) . +.It Fn rpc_broadcast_exp +Like +.Fn rpc_broadcast , +except that the initial timeout, +.Fa inittime +and the maximum timeout, +.Fa waittime +are specified in milliseconds. +The +.Fa inittime +argument +is the initial time that +.Fn rpc_broadcast_exp +waits before resending the request. +After the first resend, the re-transmission interval +increases exponentially until it exceeds +.Fa waittime . +.It Fn rpc_call +Call the remote procedure associated with +.Fa prognum , +.Fa versnum , +and +.Fa procnum +on the machine, +.Fa host . +The +.Fa inproc +argument +is used to encode the procedure's arguments, and +.Fa outproc +is used to decode the procedure's results; +.Fa in +is the address of the procedure's argument(s), and +.Fa out +is the address of where to place the result(s). +The +.Fa nettype +argument +can be any of the values listed on +.Xr rpc 3 . +This routine returns +.Dv RPC_SUCCESS +if it succeeds, +or an appropriate status is returned. +Use the +.Fn clnt_perrno +routine to translate failure status into error messages. +Warning: +.Fn rpc_call +uses the first available transport belonging +to the class +.Fa nettype , +on which it can create a connection. +You do not have control of timeouts or authentication +using this routine. +.El +.Sh SEE ALSO +.Xr printf 3 , +.Xr rpc 3 , +.Xr rpc_clnt_auth 3 , +.Xr rpc_clnt_create 3 diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3 new file mode 100644 index 0000000000..c858c9d3ce --- /dev/null +++ b/lib/libc/rpc/rpc_clnt_create.3 @@ -0,0 +1,515 @@ +.\" @(#)rpc_clnt_create.3n 1.36 93/08/31 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_clnt_create 1.5 89/07/24 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $NetBSD: rpc_clnt_create.3,v 1.2 2000/06/20 00:53:08 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_create.3,v 1.15 2006/09/17 21:27:34 ru Exp $ +.\" $DragonFly$ +.Dd May 7, 1993 +.Dt RPC_CLNT_CREATE 3 +.Os +.Sh NAME +.Nm rpc_clnt_create , +.Nm clnt_control , +.Nm clnt_create , +.Nm clnt_create_timed , +.Nm clnt_create_vers , +.Nm clnt_create_vers_timed , +.Nm clnt_destroy , +.Nm clnt_dg_create , +.Nm clnt_pcreateerror , +.Nm clnt_raw_create , +.Nm clnt_spcreateerror , +.Nm clnt_tli_create , +.Nm clnt_tp_create , +.Nm clnt_tp_create_timed , +.Nm clnt_vc_create , +.Nm rpc_createerr +.Nd "library routines for dealing with creation and manipulation of" +.Vt CLIENT +handles +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft bool_t +.Fn clnt_control "CLIENT *clnt" "const u_int req" "char *info" +.Ft "CLIENT *" +.Fn clnt_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" +.Ft "CLIENT *" +.Fn clnt_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" "const struct timeval *timeout" +.Ft "CLIENT *" +.Fn clnt_create_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype" +.Ft "CLIENT *" +.Fn clnt_create_vers_timed "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype" "const struct timeval *timeout" +.Ft void +.Fn clnt_destroy "CLIENT *clnt" +.Ft "CLIENT *" +.Fn clnt_dg_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz" +.Ft void +.Fn clnt_pcreateerror "const char *s" +.Ft "char *" +.Fn clnt_spcreateerror "const char *s" +.Ft "CLIENT *" +.Fn clnt_raw_create "const rpcprog_t prognum" "const rpcvers_t versnum" +.Ft "CLIENT *" +.Fn clnt_tli_create "const int fildes" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz" +.Ft "CLIENT *" +.Fn clnt_tp_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" +.Ft "CLIENT *" +.Fn clnt_tp_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct timeval *timeout" +.Ft "CLIENT *" +.Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "u_int sendsz" "u_int recvsz" +.Sh DESCRIPTION +RPC library routines allow C language programs to make procedure +calls on other machines across the network. +First a +.Vt CLIENT +handle is created and then the client calls a procedure to send a +request to the server. +On receipt of the request, the server calls a dispatch routine +to perform the requested service, and then sends a reply. +.Sh Routines +.Bl -tag -width YYYYYYY +.It Fn clnt_control +A function macro to change or retrieve various information +about a client object. +The +.Fa req +argument +indicates the type of operation, and +.Fa info +is a pointer to the information. +For both connectionless and connection-oriented transports, +the supported values of +.Fa req +and their argument types and what they do are: +.Bl -column "CLSET_FD_NCLOSE" "struct timeval *" "set total timeout" +.It Dv CLSET_TIMEOUT Ta "struct timeval *" Ta "set total timeout" +.It Dv CLGET_TIMEOUT Ta "struct timeval *" Ta "get total timeout" +.El +.Pp +Note: +if you set the timeout using +.Fn clnt_control , +the timeout argument passed by +.Fn clnt_call +is ignored in all subsequent calls. +.Pp +Note: +If you set the timeout value to 0, +.Fn clnt_control +immediately returns an error +.Pq Dv RPC_TIMEDOUT . +Set the timeout argument to 0 for batching calls. +.Bl -column CLSET_FD_NCLOSE "struct timeval *" +.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 "do not close fd on destroy" +.It Dv CLGET_VERS Ta "u_int32_t *" Ta "get RPC program version" +.It Dv CLSET_VERS Ta "u_int32_t *" Ta "set RPC program version" +.It Dv CLGET_XID Ta "u_int32_t *" Ta "get XID of previous call" +.It Dv CLSET_XID Ta "u_int32_t *" Ta "set XID of next call" +.El +.Pp +The following operations are valid for connectionless transports only: +.Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout" +.It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout" +.It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout" +.It Dv CLSET_CONNECT Ta Vt "int *" Ta use Xr connect 2 +.El +.Pp +The retry timeout is the time that RPC +waits for the server to reply before retransmitting the request. +The +.Fn clnt_control +function +returns +.Dv TRUE +on success and +.Dv FALSE +on failure. +.It Fn clnt_create +Generic client creation routine for program +.Fa prognum +and version +.Fa versnum . +The +.Fa host +argument +identifies the name of the remote host where the server +is located. +The +.Fa nettype +argument +indicates the class of transport protocol to use. +The transports are tried in left to right order in +.Ev NETPATH +environment variable or in top to bottom order in +the netconfig database. +The +.Fn clnt_create +function +tries all the transports of the +.Fa nettype +class available from the +.Ev NETPATH +environment variable and the netconfig database, +and chooses the first successful one. +A default timeout is set and can be modified using +.Fn clnt_control . +This routine returns +.Dv NULL +if it fails. +The +.Fn clnt_pcreateerror +routine can be used to print the reason for failure. +.Pp +Note: +.Fn clnt_create +returns a valid client handle even +if the particular version number supplied to +.Fn clnt_create +is not registered with the +.Xr rpcbind 8 +service. +This mismatch will be discovered by a +.Fn clnt_call +later (see +.Xr rpc_clnt_calls 3 ) . +.It Fn clnt_create_timed +Generic client creation routine which is similar to +.Fn clnt_create +but which also has the additional argument +.Fa timeout +that specifies the maximum amount of time allowed for +each transport class tried. +In all other respects, the +.Fn clnt_create_timed +call behaves exactly like the +.Fn clnt_create +call. +.It Fn clnt_create_vers +Generic client creation routine which is similar to +.Fn clnt_create +but which also checks for the +version availability. +The +.Fa host +argument +identifies the name of the remote host where the server +is located. +The +.Fa nettype +argument +indicates the class transport protocols to be used. +If the routine is successful it returns a client handle created for +the highest version between +.Fa vers_low +and +.Fa vers_high +that is supported by the server. +The +.Fa vers_outp +argument +is set to this value. +That is, after a successful return +.Fa vers_low +<= +.Fa *vers_outp +<= +.Fa vers_high . +If no version between +.Fa vers_low +and +.Fa vers_high +is supported by the server then the routine fails and returns +.Dv NULL . +A default timeout is set and can be modified using +.Fn clnt_control . +This routine returns +.Dv NULL +if it fails. +The +.Fn clnt_pcreateerror +routine can be used to print the reason for failure. +Note: +.Fn clnt_create +returns a valid client handle even +if the particular version number supplied to +.Fn clnt_create +is not registered with the +.Xr rpcbind 8 +service. +This mismatch will be discovered by a +.Fn clnt_call +later (see +.Xr rpc_clnt_calls 3 ) . +However, +.Fn clnt_create_vers +does this for you and returns a valid handle +only if a version within +the range supplied is supported by the server. +.It Fn clnt_create_vers_timed +Generic client creation routine which is similar to +.Fn clnt_create_vers +but which also has the additional argument +.Fa timeout +that specifies the maximum amount of time allowed for +each transport class tried. +In all other respects, the +.Fn clnt_create_vers_timed +call behaves exactly like the +.Fn clnt_create_vers +call. +.It Fn clnt_destroy +A function macro that destroys the client's RPC handle. +Destruction usually involves deallocation +of private data structures, including +.Fa clnt +itself. +Use of +.Fa clnt +is undefined after calling +.Fn clnt_destroy . +If the RPC library opened the associated file descriptor, or +.Dv CLSET_FD_CLOSE +was set using +.Fn clnt_control , +the file descriptor will be closed. +The caller should call +.Fn auth_destroy "clnt->cl_auth" +(before calling +.Fn clnt_destroy ) +to destroy the associated +.Vt AUTH +structure (see +.Xr rpc_clnt_auth 3 ) . +.It Fn clnt_dg_create +This routine creates an RPC client for the remote program +.Fa prognum +and version +.Fa versnum ; +the client uses a connectionless transport. +The remote program is located at address +.Fa svcaddr . +The +.Fa fildes +argument +is an open and bound file descriptor. +This routine will resend the call message in intervals of +15 seconds until a response is received or until the +call times out. +The total time for the call to time out is specified by +.Fn clnt_call +(see +.Fn clnt_call +in +.Xr rpc_clnt_calls 3 ) . +The retry time out and the total time out periods can +be changed using +.Fn clnt_control . +The user may set the size of the send and receive +buffers with the +.Fa sendsz +and +.Fa recvsz +arguments; +values of 0 choose suitable defaults. +This routine returns +.Dv NULL +if it fails. +.It Fn clnt_pcreateerror +Print a message to standard error indicating +why a client RPC handle could not be created. +The message is prepended with the string +.Fa s +and a colon, and appended with a newline. +.It Fn clnt_spcreateerror +Like +.Fn clnt_pcreateerror , +except that it returns a string +instead of printing to the standard error. +A newline is not appended to the message in this case. +Warning: +returns a pointer to a buffer that is overwritten +on each call. +.It Fn clnt_raw_create +This routine creates an RPC +client handle for the remote program +.Fa prognum +and version +.Fa versnum . +The transport used to pass messages to the service is +a buffer within the process's address space, +so the corresponding RPC +server should live in the same address space; +(see +.Fn svc_raw_create +in +.Xr rpc_svc_create 3 ) . +This allows simulation of RPC and measurement of +RPC overheads, such as round trip times, +without any kernel or networking interference. +This routine returns +.Dv NULL +if it fails. +The +.Fn clnt_raw_create +function +should be called after +.Fn svc_raw_create . +.It Fn clnt_tli_create +This routine creates an RPC +client handle for the remote program +.Fa prognum +and version +.Fa versnum . +The remote program is located at address +.Fa svcaddr . +If +.Fa svcaddr +is +.Dv NULL +and it is connection-oriented, it is assumed that the file descriptor +is connected. +For connectionless transports, if +.Fa svcaddr +is +.Dv NULL , +.Dv RPC_UNKNOWNADDR +error is set. +The +.Fa fildes +argument +is a file descriptor which may be open, bound and connected. +If it is +.Dv RPC_ANYFD , +it opens a file descriptor on the transport specified by +.Fa netconf . +If +.Fa fildes +is +.Dv RPC_ANYFD +and +.Fa netconf +is +.Dv NULL , +a +.Dv RPC_UNKNOWNPROTO +error is set. +If +.Fa fildes +is unbound, then it will attempt to bind the descriptor. +The user may specify the size of the buffers with the +.Fa sendsz +and +.Fa recvsz +arguments; +values of 0 choose suitable defaults. +Depending upon the type of the transport (connection-oriented +or connectionless), +.Fn clnt_tli_create +calls appropriate client creation routines. +This routine returns +.Dv NULL +if it fails. +The +.Fn clnt_pcreateerror +routine can be used to print the reason for failure. +The remote rpcbind +service (see +.Xr rpcbind 8 ) +is not consulted for the address of the remote +service. +.It Fn clnt_tp_create +Like +.Fn clnt_create +except +.Fn clnt_tp_create +tries only one transport specified through +.Fa netconf . +The +.Fn clnt_tp_create +function +creates a client handle for the program +.Fa prognum , +the version +.Fa versnum , +and for the transport specified by +.Fa netconf . +Default options are set, +which can be changed using +.Fn clnt_control +calls. +The remote rpcbind service on the host +.Fa host +is consulted for the address of the remote service. +This routine returns +.Dv NULL +if it fails. +The +.Fn clnt_pcreateerror +routine can be used to print the reason for failure. +.It Fn clnt_tp_create_timed +Like +.Fn clnt_tp_create +except +.Fn clnt_tp_create_timed +has the extra argument +.Fa timeout +which specifies the maximum time allowed for +the creation attempt to succeed. +In all other respects, the +.Fn clnt_tp_create_timed +call behaves exactly like the +.Fn clnt_tp_create +call. +.It Fn clnt_vc_create +This routine creates an RPC +client for the remote program +.Fa prognum +and version +.Fa versnum ; +the client uses a connection-oriented transport. +The remote program is located at address +.Fa svcaddr . +The +.Fa fildes +argument +is an open and bound file descriptor. +The user may specify the size of the send and receive buffers +with the +.Fa sendsz +and +.Fa recvsz +arguments; +values of 0 choose suitable defaults. +This routine returns +.Dv NULL +if it fails. +The address +.Fa svcaddr +should not be +.Dv NULL +and should point to the actual address of the remote program. +The +.Fn clnt_vc_create +function +does not consult the remote rpcbind service for this information. +.It Xo +.Vt "struct rpc_createerr" Va rpc_createerr ; +.Xc +A global variable whose value is set by any RPC +client handle creation routine +that fails. +It is used by the routine +.Fn clnt_pcreateerror +to print the reason for the failure. +.El +.Sh SEE ALSO +.Xr rpc 3 , +.Xr rpc_clnt_auth 3 , +.Xr rpc_clnt_calls 3 , +.Xr rpcbind 8 diff --git a/include/rpc/rpc_com.h b/lib/libc/rpc/rpc_com.h similarity index 50% copy from include/rpc/rpc_com.h copy to lib/libc/rpc/rpc_com.h index 2cf5995d2d..ce28bfbe67 100644 --- a/include/rpc/rpc_com.h +++ b/lib/libc/rpc/rpc_com.h @@ -5,26 +5,31 @@ * 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 + * + * @(#)rpc_com.h 1.11 93/07/05 SMI + * $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_com.h,v 1.8 2006/02/27 22:10:59 deischen Exp $ + * $DragonFly$ */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. @@ -34,22 +39,15 @@ * 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 , + * but as it contains only non-exported interfaces, it was moved here. */ -#ifndef _RPC_RPCCOM_H -#define _RPC_RPCCOM_H +#ifndef _RPC_RPC_COM_H_ +#define _RPC_RPC_COM_H_ -/* From: #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ +#include -#ifdef __cplusplus -extern "C" { -#endif - -/* - * 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. @@ -57,22 +55,40 @@ extern "C" { #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(int); +extern int __rpc_dtbsize(void); +extern struct netconfig * __rpcgettp(int); +extern int __rpc_get_default_domain(char **); + +char *__rpc_taddr2uaddr_af(int, const struct netbuf *); +struct netbuf *__rpc_uaddr2taddr_af(int, const char *); +int __rpc_fixup_addr(struct netbuf *, const struct netbuf *); +int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **); +int __rpc_seman2socktype(int); +int __rpc_socktype2seman(int); +void *rpc_nullproc(CLIENT *); +int __rpc_sockisbound(int); + +struct netbuf *__rpcb_findaddr_timed(rpcprog_t, rpcvers_t, + const struct netconfig *, const char *host, CLIENT **clpp, + struct timeval *tp); + +bool_t __rpc_control(int,void *); + +char *_get_next_token(char *, int); + +bool_t __svc_clean_idle(fd_set *, int, bool_t); +bool_t __xdrrec_setnonblock(XDR *, int); +bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t); +void __xprt_unregister_unlocked(SVCXPRT *); + +SVCXPRT **__svc_xports; +int __svc_maxrec; -#ifdef __cplusplus -} -#endif +__END_DECLS -#endif /* _RPC_RPCCOM_H */ +#endif /* _RPC_RPC_COM_H_ */ diff --git a/lib/libc/rpc/rpc_commondata.c b/lib/libc/rpc/rpc_commondata.c index 06227653dd..2fc0800373 100644 --- a/lib/libc/rpc/rpc_commondata.c +++ b/lib/libc/rpc/rpc_commondata.c @@ -27,11 +27,15 @@ * Mountain View, California 94043 * * @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/rpc_commondata.c,v 1.7 1999/08/28 00:00:45 peter Exp $ + * $NetBSD: rpc_commondata.c,v 1.7 2000/06/02 23:11:13 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_commondata.c,v 1.9 2002/03/22 23:18:37 obrien Exp $ * $DragonFly: src/lib/libc/rpc/rpc_commondata.c,v 1.2 2003/06/17 04:26:45 dillon Exp $ */ +#include "namespace.h" #include +#include "un-namespace.h" + /* * This file should only contain common data (global data) that is exported * by public interfaces @@ -39,4 +43,3 @@ 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 4f28d01db7..bf97c3165a 100644 --- a/lib/libc/rpc/rpc_dtablesize.c +++ b/lib/libc/rpc/rpc_dtablesize.c @@ -28,12 +28,16 @@ * * @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro * @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/rpc_dtablesize.c,v 1.10 1999/08/28 00:00:45 peter Exp $ + * $NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_dtablesize.c,v 1.15 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/rpc_dtablesize.c,v 1.3 2005/01/31 22:29:38 dillon Exp $ */ -#include +#include "namespace.h" #include +#include "un-namespace.h" + +int _rpc_dtablesize(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 0000000000..d97d58879b --- /dev/null +++ b/lib/libc/rpc/rpc_generic.c @@ -0,0 +1,831 @@ +/* + * 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 + * @(#)rpc_generic.c 1.17 94/04/24 SMI + * $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_generic.c,v 1.14 2007/09/20 22:35:24 matteo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * rpc_generic.c, Misc routines for RPC. + * + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" +#include "rpc_com.h" +#include "mt_misc.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 + { "local", AF_LOCAL, 0 } +}; + +#if 0 +static char *strlocase(char *); +#endif +static int getnettype(const char *); + +/* + * Cache the result of getrlimit(), so we don't have to do an + * expensive call every time. + */ +int +__rpc_dtbsize(void) +{ + 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(int af, int proto, + int size) /* Size requested */ +{ + int maxsize, defsize; + + maxsize = 256 * 1024; /* XXX */ + switch (proto) { + case IPPROTO_TCP: + defsize = 64 * 1024; /* XXX */ + break; + case IPPROTO_UDP: + defsize = UDPMSGSIZE; + break; + default: + defsize = RPC_MAXDATASIZE; + break; + } + if (size == 0) + return defsize; + + /* 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(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(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 + * If nettype is NULL, it defaults to NETPATH. + */ +static int +getnettype(const char *nettype) +{ + int i; + + if ((nettype == NULL) || (nettype[0] == 0)) { + return (_RPC_NETPATH); /* Default */ + } + +#if 0 + nettype = strlocase(nettype); +#endif + for (i = 0; _rpctypelist[i].name; i++) + if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { + return (_rpctypelist[i].type); + } + return (_rpctypelist[i].type); +} + +/* + * For the given nettype (tcp or udp only), return the first structure found. + * This should be freed by calling freenetconfigent() + */ +struct netconfig * +__rpc_getconfip(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; + + 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] == 0)) { + return (NULL); + } + dummy = getnetconfigent(netid); + return (dummy); +} + +/* + * Returns the type of the nettype, which should then be used with + * __rpc_getconf(). + */ +void * +__rpc_setconf(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())) + goto failed; + 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); + goto failed; + } + handle->nflag = FALSE; + break; + default: + goto failed; + } + + return (handle); + +failed: + free(handle); + return (NULL); +} + +/* + * Returns the next netconfig struct for the given "net" type. + * __rpc_setconf() should have been called previously. + */ +struct netconfig * +__rpc_getconf(void *vhandle) +{ + struct handle *handle; + struct netconfig *nconf; + + handle = (struct handle *)vhandle; + if (handle == NULL) { + return (NULL); + } + for (;;) { + if (handle->nflag) + nconf = getnetpath(handle->nhandle); + else + nconf = getnetconfig(handle->nhandle); + if (nconf == NULL) + break; + if ((nconf->nc_semantics != NC_TPI_CLTS) && + (nconf->nc_semantics != NC_TPI_COTS) && + (nconf->nc_semantics != NC_TPI_COTS_ORD)) + continue; + switch (handle->nettype) { + case _RPC_VISIBLE: + if (!(nconf->nc_flag & NC_VISIBLE)) + continue; + /* 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(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(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(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) == 0 || ( + strcmp(nconf->nc_netid, "unix") == 0 && + strcmp(na_cvt[i].netid, "local") == 0)) { + sip->si_af = na_cvt[i].af; + sip->si_proto = na_cvt[i].protocol; + sip->si_socktype = + __rpc_seman2socktype((int)nconf->nc_semantics); + if (sip->si_socktype == -1) + return 0; + sip->si_alen = __rpc_get_a_size(sip->si_af); + return 1; + } + + return 0; +} + +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; + struct netconfig *nconf; + + nconf = getnetconfigent("local"); + + for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { + if (na_cvt[i].af == sip->si_af && + na_cvt[i].protocol == sip->si_proto) { + if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { + if (netid) + *netid = "unix"; + } else { + if (netid) + *netid = na_cvt[i].netid; + } + if (nconf != NULL) + freenetconfigent(nconf); + return 1; + } + } + if (nconf != NULL) + freenetconfigent(nconf); + + return 0; +} + +char * +taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) +{ + struct __rpc_sockinfo si; + + if (!__rpc_nconf2sockinfo(nconf, &si)) + return NULL; + return __rpc_taddr2uaddr_af(si.si_af, nbuf); +} + +struct netbuf * +uaddr2taddr(const struct netconfig *nconf, const char *uaddr) +{ + struct __rpc_sockinfo si; + + if (!__rpc_nconf2sockinfo(nconf, &si)) + return NULL; + return __rpc_uaddr2taddr_af(si.si_af, uaddr); +} + +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; + if (asprintf(&ret, "%.*s", (int)(sun->sun_len - + offsetof(struct sockaddr_un, sun_path)), + sun->sun_path) < 0) + return (NULL); + 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; + + port = 0; + sin = NULL; + addrstr = strdup(uaddr); + if (addrstr == NULL) + return NULL; + + /* + * AF_LOCAL addresses are expected to be absolute + * pathnames, anything else will be AF_INET or AF_INET6. + */ + if (*addrstr != '/') { + p = strrchr(addrstr, '.'); + if (p == NULL) + goto out; + portlo = (unsigned)atoi(p + 1); + *p = '\0'; + + p = strrchr(addrstr, '.'); + if (p == NULL) + goto out; + porthi = (unsigned)atoi(p + 1); + *p = '\0'; + port = (porthi << 8) | portlo; + } + + ret = (struct netbuf *)malloc(sizeof *ret); + if (ret == NULL) + goto out; + + switch (af) { + case AF_INET: + sin = (struct sockaddr_in *)malloc(sizeof *sin); + if (sin == NULL) + goto out; + memset(sin, 0, sizeof *sin); + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { + free(sin); + free(ret); + ret = NULL; + goto out; + } + 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(sin6); + 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); + ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); + ret->buf = sun; + 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 c09ee58280..cc51c73746 100644 --- a/lib/libc/rpc/rpc_prot.c +++ b/lib/libc/rpc/rpc_prot.c @@ -28,7 +28,8 @@ * * @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro * @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/rpc_prot.c,v 1.8 1999/08/28 00:00:46 peter Exp $ + * $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_prot.c,v 1.13 2007/11/20 01:51:20 jb Exp $ * $DragonFly: src/lib/libc/rpc/rpc_prot.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -45,13 +46,20 @@ * routines are also in this program. */ +#include "namespace.h" #include +#include + #include +#include "un-namespace.h" + +static void accepted(enum accept_stat, struct rpc_err *); +static void rejected(enum reject_stat, struct rpc_err *); /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ -struct opaque_auth _null_auth; +extern struct opaque_auth _null_auth; /* * XDR an opaque authentication struct @@ -61,6 +69,9 @@ bool_t xdr_opaque_auth(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)); @@ -73,7 +84,11 @@ xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap) bool_t xdr_des_block(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 * * * * * * * * * * * * * * * */ @@ -84,11 +99,17 @@ xdr_des_block(XDR *xdrs, des_block *blkp) bool_t xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar) { + enum accept_stat *par_stat; + + assert(xdrs != NULL); + assert(ar != NULL); + + par_stat = &ar->ar_stat; /* personalized union, rather than calling xdr_union */ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) return (FALSE); - if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) + if (! xdr_enum(xdrs, (enum_t *) par_stat)) return (FALSE); switch (ar->ar_stat) { @@ -99,7 +120,11 @@ xdr_accepted_reply(XDR *xdrs, struct accepted_reply *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 */ @@ -111,9 +136,16 @@ xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar) bool_t xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr) { + enum reject_stat *prj_stat; + enum auth_stat *prj_why; + + assert(xdrs != NULL); + assert(rr != NULL); + + prj_stat = &rr->rj_stat; /* personalized union, rather than calling xdr_union */ - if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) + if (! xdr_enum(xdrs, (enum_t *) prj_stat)) return (FALSE); switch (rr->rj_stat) { @@ -123,14 +155,17 @@ xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr) return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); case AUTH_ERROR: - return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); + prj_why = &rr->rj_why; + return (xdr_enum(xdrs, (enum_t *) prj_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 } }; /* @@ -139,12 +174,22 @@ static struct xdr_discrim reply_dscrm[3] = { bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg) { + enum msg_type *prm_direction; + enum reply_stat *prp_stat; + + assert(xdrs != NULL); + assert(rmsg != NULL); + + prm_direction = &rmsg->rm_direction; + prp_stat = &rmsg->rm_reply.rp_stat; + if ( xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && - xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && + xdr_enum(xdrs, (enum_t *) prm_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)); + return (xdr_union(xdrs, (enum_t *) prp_stat, + (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm, + NULL_xdrproc_t)); return (FALSE); } @@ -157,16 +202,22 @@ xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg) bool_t xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg) { + enum msg_type *prm_direction; + + assert(xdrs != NULL); + assert(cmsg != NULL); + + prm_direction = &cmsg->rm_direction; cmsg->rm_direction = CALL; cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; if ( (xdrs->x_op == XDR_ENCODE) && xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && - xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + xdr_enum(xdrs, (enum_t *) prm_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); } @@ -176,6 +227,8 @@ static void accepted(enum accept_stat acpt_stat, struct rpc_err *error) { + assert(error != NULL); + switch (acpt_stat) { case PROG_UNAVAIL: @@ -202,32 +255,33 @@ accepted(enum accept_stat acpt_stat, struct rpc_err *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 rejected(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; } /* @@ -237,6 +291,9 @@ void _seterr_reply(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) { @@ -244,7 +301,7 @@ _seterr_reply(struct rpc_msg *msg, struct rpc_err *error) if (msg->acpted_rply.ar_stat == SUCCESS) { error->re_status = RPC_SUCCESS; return; - }; + } accepted(msg->acpted_rply.ar_stat, error); break; @@ -254,7 +311,7 @@ _seterr_reply(struct rpc_msg *msg, struct rpc_err *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) { @@ -272,6 +329,22 @@ _seterr_reply(struct rpc_msg *msg, struct rpc_err *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_secure.3 b/lib/libc/rpc/rpc_secure.3 index 73b3c87022..a61449311a 100644 --- a/lib/libc/rpc/rpc_secure.3 +++ b/lib/libc/rpc/rpc_secure.3 @@ -24,7 +24,7 @@ .Ft int .Fn getnetname "char *name" .Ft int -.Fn host2netname "char *name" "char *host" "char *domain" +.Fn host2netname "char *name" "const char *host" "const char *domain" .Ft int .Fn key_decryptsession "const char *remotename" "des_block *deskey" .Ft int @@ -38,7 +38,7 @@ .Ft int .Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist" .Ft int -.Fn user2netname "char *name" "uid_t uid" "char *domain" +.Fn user2netname "char *name" "const uid_t uid" "const char *domain" .Sh DESCRIPTION These routines are part of the .Tn RPC diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc_soc.3 similarity index 85% copy from lib/libc/rpc/rpc.3 copy to lib/libc/rpc/rpc_soc.3 index 5450746dc1..f80b8049fd 100644 --- a/lib/libc/rpc/rpc.3 +++ b/lib/libc/rpc/rpc_soc.3 @@ -1,12 +1,77 @@ .\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI -.\" $FreeBSD: src/lib/libc/rpc/rpc.3,v 1.11.2.5 2001/12/14 18:33:56 ru Exp $ -.\" $DragonFly: src/lib/libc/rpc/rpc.3,v 1.8 2008/05/01 22:06:06 swildner Exp $ +.\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_soc.3,v 1.12 2003/02/06 11:04:47 charnier Exp $ +.\" $DragonFly$ .\" .Dd February 16, 1988 -.Dt RPC 3 +.Dt RPC_SOC 3 .Os .Sh NAME -.Nm rpc +.Nm rpc_soc , +.Nm auth_destroy , +.Nm authnone_create , +.Nm authunix_create , +.Nm authunix_create_default , +.Nm callrpc , +.Nm clnt_broadcast , +.Nm clnt_call , +.Nm clnt_control , +.Nm clnt_create , +.Nm clnt_destroy , +.Nm clnt_freeres , +.Nm clnt_geterr , +.Nm clnt_pcreateerror , +.Nm clnt_perrno , +.Nm clnt_perror , +.Nm clnt_spcreateerror , +.Nm clnt_sperrno , +.Nm clnt_sperror , +.Nm clntraw_create , +.Nm clnttcp_create , +.Nm clntudp_bufcreate , +.Nm clntudp_create , +.Nm clntunix_create , +.Nm get_myaddress , +.Nm pmap_getmaps , +.Nm pmap_getport , +.Nm pmap_rmtcall , +.Nm pmap_set , +.Nm pmap_unset , +.Nm registerrpc , +.Nm rpc_createerr , +.Nm svc_destroy , +.Nm svc_fds , +.Nm svc_fdset , +.Nm svc_getargs , +.Nm svc_getcaller , +.Nm svc_getreq , +.Nm svc_getreqset , +.Nm svc_register , +.Nm svc_run , +.Nm svc_sendreply , +.Nm svc_unregister , +.Nm svcerr_auth , +.Nm svcerr_decode , +.Nm svcerr_noproc , +.Nm svcerr_noprog , +.Nm svcerr_progvers , +.Nm svcerr_systemerr , +.Nm svcerr_weakauth , +.Nm svcfd_create , +.Nm svcunixfd_create , +.Nm svcraw_create , +.Nm svcunix_create , +.Nm xdr_accepted_reply , +.Nm xdr_authunix_parms , +.Nm xdr_callhdr , +.Nm xdr_callmsg , +.Nm xdr_opaque_auth , +.Nm xdr_pmap , +.Nm xdr_pmaplist , +.Nm xdr_rejected_reply , +.Nm xdr_replymsg , +.Nm xprt_register , +.Nm xprt_unregister .Nd "library routines for remote procedure calls" .Sh LIBRARY .Lb libc @@ -17,6 +82,18 @@ See .Sx DESCRIPTION for function declarations. .Sh DESCRIPTION +.Bf -symbolic +The +.Fn svc_* +and +.Fn clnt_* +functions described in this page are the old, TS-RPC +interface to the XDR and RPC library, and exist for backward compatibility. +The new interface is described in the pages +referenced from +.Xr rpc 3 . +.Ef +.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 @@ -80,8 +157,9 @@ Create and return an authentication handle that contains .Ux authentication information. -The parameter +The .Fa host +argument is the name of the machine on which the information was created; .Fa uid @@ -103,7 +181,7 @@ It is easy to impersonate a user. .Pp Calls .Fn authunix_create -with the appropriate parameters. +with the appropriate arguments. .Pp .It Xo .Ft int @@ -113,9 +191,9 @@ with the appropriate parameters. .Fa "u_long versnum" .Fa "u_long procnum" .Fa "xdrproc_t inproc" -.Fa "char *in" +.Fa "void *in" .Fa "xdrproc_t outproc" -.Fa "char *out" +.Fa "void *out" .Fc .Xc .Pp @@ -126,13 +204,14 @@ and .Fa procnum on the machine .Fa host . -The parameter +The .Fa in +argument 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 +is used to encode the procedure's arguments, and .Fa outproc is used to decode the procedure's results. This routine returns zero if it succeeds, or the value of @@ -163,7 +242,7 @@ this routine. .Fa "char *in" .Fa "xdrproc_t outproc" .Fa "char *out" -.Fa "bool_t (*eachresult)(caddr_t, struct sockaddr_in *) +.Fa "bool_t (*eachresult)(caddr_t, struct sockaddr_in *)" .Fc .Xc .Pp @@ -224,13 +303,14 @@ which is obtained with an .Tn RPC client creation routine such as .Fn clnt_create . -The parameter +The .Fa in +argument 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 +is used to encode the procedure's arguments, and .Fa outproc is used to decode the procedure's results; .Fa tout @@ -265,10 +345,14 @@ Otherwise, the socket remains open. .Xc .Pp Generic client creation routine. +The .Fa host +argument identifies the name of the remote host where the server is located. +The .Fa proto +argument indicates which kind of transport protocol to use. The currently supported values for this field are @@ -297,7 +381,9 @@ large arguments or return huge results. .Pp A macro used to change or retrieve various information about a client object. +The .Fa req +argument indicates the type of operation, and .Fa info is a pointer to the information. @@ -319,7 +405,7 @@ and their argument types and what they do are: .Pp Note: if you set the timeout using .Fn clnt_control , -the timeout parameter passed to +the timeout argument passed to .Fn clnt_call will be ignored in all future calls. .Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in" @@ -338,7 +424,6 @@ only: .It Dv CLGET_RETRY_TIMEOUT Ta Xo .Vt "struct timeval" Ta "get the retry timeout" .Xc -.It Dv CLSET_CONNECT Ta Vt "int" Ta use Xr connect 2 .El .Pp The retry timeout is the time that @@ -356,8 +441,9 @@ A macro that frees any data allocated by the system when it decoded the results of an .Tn RPC call. -The parameter +The .Fa out +argument is the address of the results, and .Fa outproc is the @@ -393,6 +479,7 @@ handle could not be created. The message is prepended with string .Fa s and a colon. +A newline is appended at the end of the message. Used when a .Fn clnt_create , .Fn clntraw_create , @@ -411,6 +498,7 @@ call fails. Print a message to standard error corresponding to the condition indicated by .Fa stat . +A newline is appended at the end of the message. Used after .Fn callrpc . .Pp @@ -427,6 +515,7 @@ is the handle used to do the call. The message is prepended with string .Fa s and a colon. +A newline is appended at the end of the message. Used after .Fn clnt_call . .Pp @@ -459,10 +548,10 @@ 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 +The .Fn clnt_sperrno +function is used instead of .Fn clnt_perrno if the program does not have a standard error (as a program @@ -557,10 +646,11 @@ 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 +.Xr rpcbind 8 service is consulted for this information). -The parameter +The .Fa sockp +argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets @@ -571,10 +661,11 @@ Since uses buffered .Tn I/O , the user may specify the size of the send and receive buffers -with the parameters +with the .Fa sendsz and -.Fa recvsz ; +.Fa recvsz +arguments; values of zero choose suitable defaults. This routine returns .Dv NULL @@ -609,10 +700,11 @@ 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 +.Xr rpcbind 8 service is consulted for this information). -The parameter +The .Fa sockp +argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets @@ -664,10 +756,11 @@ 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 +.Xr rpcbind 8 service is consulted for this information). -The parameter +The .Fa sockp +argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets @@ -688,6 +781,55 @@ for sending and receiving messages. .Pp .It Xo +.Ft "CLIENT *" +.Xc +.It Xo +.Fo clntunix_create +.Fa "struct sockaddr_un *raddr" +.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 local +program +.Fa prognum , +version +.Fa versnum ; +the client uses +.Ux Ns -domain +sockets as a transport. +The local program is located at the +.Fa *raddr . +The +.Fa sockp +argument +is a socket; if it is +.Dv RPC_ANYSOCK , +then this routine opens a new one and sets +.Fa sockp . +Since +.Ux Ns -based +.Tn RPC +uses buffered +.Tn I/O , +the user may specify the size of the send and receive buffers +with the +.Fa sendsz +and +.Fa recvsz +arguments; +values of zero choose suitable defaults. +This routine returns +.Dv NULL +if it fails. +.Pp +.It Xo .Ft int .Xc .It Xo @@ -712,7 +854,7 @@ Returns zero on success, non-zero on failure. .Xc .Pp A user interface to the -.Xr portmap 8 +.Xr rpcbind 8 service, which returns a list of the current .Tn RPC program\-to\-port mappings @@ -739,7 +881,7 @@ uses this routine. .Xc .Pp A user interface to the -.Xr portmap 8 +.Xr rpcbind 8 service, which returns the port number on which waits a service that supports program number .Fa prognum , @@ -758,7 +900,7 @@ or that the .Tn RPC system failed to contact the remote -.Xr portmap 8 +.Xr rpcbind 8 service. In the latter case, the global variable .Va rpc_createerr @@ -785,9 +927,9 @@ status. .Xc .Pp A user interface to the -.Xr portmap 8 +.Xr rpcbind 8 service, which instructs -.Xr portmap 8 +.Xr rpcbind 8 on the host at .Tn IP address @@ -795,12 +937,13 @@ address to make an .Tn RPC call on your behalf to a procedure on that host. -The parameter +The .Fa portp +argument will be modified to the program's port number if the procedure succeeds. -The definitions of other parameters are discussed +The definitions of other arguments are discussed in .Fn callrpc and @@ -818,13 +961,13 @@ See also .Xc .Pp A user interface to the -.Xr portmap 8 +.Xr rpcbind 8 service, which establishes a mapping between the triple .Pq Fa prognum , versnum , protocol and .Fa port on the machine's -.Xr portmap 8 +.Xr rpcbind 8 service. The value of .Fa protocol @@ -842,13 +985,13 @@ Automatically done by .Xc .Pp A user interface to the -.Xr portmap 8 +.Xr rpcbind 8 service, which destroys all mapping between the triple .Pq Fa prognum , versnum , * and .Fa ports on the machine's -.Xr portmap 8 +.Xr rpcbind 8 service. This routine returns one if it succeeds, zero otherwise. @@ -877,11 +1020,11 @@ version and procedure .Fa procnum , .Fa procname -is called with a pointer to its parameter(s); +is called with a pointer to its argument(s); .Fa progname should return a pointer to its static result(s); .Fa inproc -is used to decode the parameters while +is used to decode the arguments while .Fa outproc is used to encode the results. This routine returns zero if the registration succeeded, \-1 @@ -930,7 +1073,7 @@ is undefined after calling this routine. A global variable reflecting the .Tn RPC service side's -read file descriptor bit mask; it is suitable as a template parameter +read file descriptor bit mask; it is suitable as a template argument to the .Xr select 2 system call. @@ -987,8 +1130,9 @@ associated with the .Tn RPC service transport handle, .Fa xprt . -The parameter +The .Fa in +argument is the address where the arguments will be placed; .Fa inproc is the @@ -1064,7 +1208,7 @@ with the service dispatch procedure, If .Fa protocol is zero, the service is not registered with the -.Xr portmap 8 +.Xr rpcbind 8 service. If .Fa protocol @@ -1073,7 +1217,7 @@ is non-zero, then a mapping of the triple to .Fa xprt\->xp_port is established with the local -.Xr portmap 8 +.Xr rpcbind 8 service (generally .Fa protocol is zero, @@ -1116,8 +1260,9 @@ Called by an .Tn RPC service's dispatch routine to send the results of a remote procedure call. -The parameter +The .Fa xprt +argument is the request's associated transport handle; .Fa outproc is the @@ -1158,7 +1303,7 @@ a remote procedure call due to an authentication error. .Xc .Pp Called by a service dispatch routine that cannot successfully -decode its parameters. +decode its arguments. See also .Fn svc_getargs . .Pp @@ -1219,7 +1364,7 @@ it may call this routine. .Pp Called by a service dispatch routine that refuses to perform a remote procedure call due to insufficient -authentication parameters. +authentication arguments. The routine calls .Fn svcerr_auth xprt AUTH_TOOWEAK . .Pp @@ -1271,7 +1416,7 @@ 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 +.Fa xprt\->xp_fd is the transport's socket descriptor, and .Fa xprt\->xp_port is the transport's port number. @@ -1290,6 +1435,64 @@ choose suitable defaults. .Ft "SVCXPRT *" .Xc .It Xo +.Fn svcunix_create "int sock" "u_int send_buf_size" "u_int recv_buf_size" "char *path" +.Xc +.Pp +This routine creates a +.Ux 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. +The +.Fa *path +argument +is a variable-length file system pathname of +at most 104 characters. +This file is +.Em not +removed when the socket is closed. +The +.Xr unlink 2 +system call must be used to remove the file. +Upon completion, +.Fa xprt\->xp_fd +is the transport's socket descriptor. +This routine returns +.Dv NULL +if it fails. +Since +.Ux 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 svcunixfd_create "int fd" "u_int sendsize" "u_int recvsize" +.Xc +.Pp +Create a service on top of any open descriptor. +The +.Fa sendsize +and +.Fa recvsize +arguments +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 svcfd_create "int fd" "u_int sendsize" "u_int recvsize" .Xc .Pp @@ -1299,9 +1502,11 @@ this descriptor is a connected socket for a stream protocol such as .Tn TCP . +The .Fa sendsize and .Fa recvsize +arguments indicate sizes for the send and receive buffers. If they are zero, a reasonable default is chosen. @@ -1327,7 +1532,7 @@ If the socket is not bound to a local port, then this routine binds it to an arbitrary port. Upon completion, -.Fa xprt\->xp_sock +.Fa xprt\->xp_fd is the transport's socket descriptor, and .Fa xprt\->xp_port is the transport's port number. @@ -1422,11 +1627,11 @@ package. .Fn xdr_pmap "XDR *xdrs" "struct pmap *regs" .Xc .Pp -Used for describing parameters to various -.Xr portmap 8 +Used for describing arguments to various +.Xr rpcbind 8 procedures, externally. This routine is useful for users who wish to generate -these parameters without using the +these arguments without using the .Fn pmap_* interface. .Pp @@ -1437,7 +1642,7 @@ interface. .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 +these arguments without using the .Fn pmap_* interface. .Pp diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c new file mode 100644 index 0000000000..059877527d --- /dev/null +++ b/lib/libc/rpc/rpc_soc.c @@ -0,0 +1,516 @@ +/* + * 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 + * @(#)rpc_soc.c 1.17 94/04/24 SMI; 1.41 89/05/02 Copyr 1988 Sun Micro + * $NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/rpc_soc.c,v 1.15 2006/02/27 22:10:59 deischen Exp $ + * $DragonFly$ + */ + +/* + * 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. + */ + +#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 "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + +#include "rpc_com.h" +#include "mt_misc.h" + +static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t, + int *, u_int, u_int, char *); +static SVCXPRT *svc_com_create(int, u_int, u_int, char *); +static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *); + +/* XXX */ +#define IN4_LOCALHOST_STRING "127.0.0.1" +#define IN6_LOCALHOST_STRING "::1" + +/* + * A common clnt create routine + */ +static CLIENT * +clnt_com_create(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. + */ + CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); + *sockp = fd; + } + 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) + _close(fd); + freenetconfigent(nconf); + mutex_unlock(&rpcsoc_lock); + return (NULL); +} + +CLIENT * +clntudp_bufcreate(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); + } + CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait); + return (cl); +} + +CLIENT * +clntudp_create(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(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(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(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) { + syslog(LOG_ERR, "Could not get %s transport", netid); + return (NULL); + } + if (fd == RPC_ANYSOCK) { + fd = __rpc_nconf2fd(nconf); + if (fd == -1) { + freenetconfigent(nconf); + 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); + freenetconfigent(nconf); + if (svc == NULL) { + if (madefd) + _close(fd); + return (NULL); + } + port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); + svc->xp_port = ntohs(port); + return (svc); +} + +SVCXPRT * +svctcp_create(int fd, u_int sendsize, u_int recvsize) +{ + + return svc_com_create(fd, sendsize, recvsize, "tcp"); +} + +SVCXPRT * +svcudp_bufcreate(int fd, u_int sendsz, u_int recvsz) +{ + + return svc_com_create(fd, sendsz, recvsz, "udp"); +} + +SVCXPRT * +svcfd_create(int fd, u_int sendsize, u_int recvsize) +{ + + return svc_fd_create(fd, sendsize, recvsize); +} + + +SVCXPRT * +svcudp_create(int fd) +{ + + return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"); +} + +SVCXPRT * +svcraw_create(void) +{ + + return svc_raw_create(); +} + +int +get_myaddress(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(const char *host, int prognum, int versnum, int procnum, + xdrproc_t inproc, void *in, xdrproc_t outproc, void *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(int prognum, int versnum, int procnum, char *(*progname)(char *), + xdrproc_t inproc, xdrproc_t 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(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(u_long prog, /* program number */ + u_long vers, /* version number */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + void *argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + void *resultsp, /* pointer to results */ + resultproc_t eachresult) /* call with each result obtained */ +{ + + 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(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); +} + +/* + * Create a client handle for a unix connection. Obsoleted by clnt_vc_create() + */ +CLIENT * +clntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, + u_int sendsz, u_int recvsz) +{ + struct netbuf *svcaddr; + struct netconfig *nconf; + CLIENT *cl; + int len; + + cl = NULL; + nconf = NULL; + svcaddr = NULL; + if ((raddr->sun_len == 0) || + ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) || + ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) { + if (svcaddr != NULL) + free(svcaddr); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + return(cl); + } + if (*sockp < 0) { + *sockp = _socket(AF_LOCAL, SOCK_STREAM, 0); + len = raddr->sun_len = SUN_LEN(raddr); + 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) + _close(*sockp); + goto done; + } + } + svcaddr->buf = raddr; + svcaddr->len = raddr->sun_len; + svcaddr->maxlen = sizeof (struct sockaddr_un); + cl = clnt_vc_create(*sockp, svcaddr, prog, + vers, sendsz, recvsz); +done: + free(svcaddr->buf); + free(svcaddr); + return(cl); +} + +/* + * Creates, registers, and returns a (rpc) unix based transporter. + * Obsoleted by svc_vc_create(). + */ +SVCXPRT * +svcunix_create(int sock, u_int sendsize, u_int recvsize, char *path) +{ + struct netconfig *nconf; + void *localhandle; + struct sockaddr_un sun; + struct sockaddr *sa; + struct t_bind taddr; + SVCXPRT *xprt; + int addrlen; + + xprt = (SVCXPRT *)NULL; + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } + if (nconf == NULL) + return(xprt); + + if ((sock = __rpc_nconf2fd(nconf)) < 0) + goto done; + + memset(&sun, 0, sizeof sun); + sun.sun_family = AF_LOCAL; + if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= + sizeof(sun.sun_path)) + goto done; + sun.sun_len = SUN_LEN(&sun); + addrlen = sizeof (struct sockaddr_un); + sa = (struct sockaddr *)&sun; + + if (_bind(sock, sa, addrlen) < 0) + goto done; + + taddr.addr.len = taddr.addr.maxlen = addrlen; + taddr.addr.buf = malloc(addrlen); + if (taddr.addr.buf == NULL) + goto done; + memcpy(taddr.addr.buf, sa, addrlen); + + if (nconf->nc_semantics != NC_TPI_CLTS) { + if (_listen(sock, SOMAXCONN) < 0) { + free(taddr.addr.buf); + goto done; + } + } + + xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize); + +done: + endnetconfig(localhandle); + return(xprt); +} + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. Obsoleted by svc_fd_create(); + */ +SVCXPRT * +svcunixfd_create(int fd, u_int sendsize, u_int recvsize) +{ + return (svc_fd_create(fd, sendsize, recvsize)); +} + +#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 0000000000..3eeacd0bcd --- /dev/null +++ b/lib/libc/rpc/rpc_svc_calls.3 @@ -0,0 +1,268 @@ +.\" @(#)rpc_svc_calls.3n 1.28 93/05/10 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_svc_calls 1.5 89/07/25 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $NetBSD: rpc_svc_calls.3,v 1.1 2000/06/02 23:11:13 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_calls.3,v 1.10 2005/11/23 16:44:23 ru Exp $ +.\" $DragonFly$ +.Dd May 3, 1993 +.Dt RPC_SVC_CALLS 3 +.Os +.Sh NAME +.Nm svc_dg_enablecache , +.Nm svc_exit , +.Nm svc_fdset , +.Nm svc_freeargs , +.Nm svc_getargs , +.Nm svc_getreq_common , +.Nm svc_getreq_poll , +.Nm svc_getreqset , +.Nm svc_getrpccaller , +.Nm svc_pollset , +.Nm svc_run , +.Nm svc_sendreply +.Nd library routines for RPC servers +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft int +.Fn svc_dg_enablecache "SVCXPRT *xprt" "const unsigned cache_size" +.Ft void +.Fn svc_exit "void" +.Ft bool_t +.Fn svc_freeargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in" +.Ft bool_t +.Fn svc_getargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in" +.Ft void +.Fn svc_getreq_common "const int fd" +.Ft void +.Fn svc_getreq_poll "struct pollfd *pfdp" "const int pollretval" +.Ft void +.Fn svc_getreqset "fd_set * rdfds" +.Ft "struct netbuf *" +.Fn svc_getrpccaller "const SVCXPRT *xprt" +.Ft "struct cmsgcred *" +.Fn __svc_getcallercreds "const SVCXPRT *xprt" +.Vt struct pollfd svc_pollset[FD_SETSIZE]; +.Ft void +.Fn svc_run "void" +.Ft bool_t +.Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "void *out" +.Sh DESCRIPTION +These routines are part of the +RPC +library which allows C language programs to make procedure +calls on other machines across the network. +.Pp +These routines are associated with the server side of the +RPC mechanism. +Some of them are called by the server side dispatch function, +while others +(such as +.Fn svc_run ) +are called when the server is initiated. +.\" .Pp +.\" In the current implementation, the service transport handle, +.\" .Dv SVCXPRT , +.\" contains a single data area for decoding arguments and encoding results. +.\" Therefore, this structure cannot be freely shared between threads that call +.\" functions that do this. +.\" Routines on this page that are affected by this +.\" restriction are marked as unsafe for MT applications. +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt SVCXPRT +data structure. +.Bl -tag -width __svc_getcallercreds() +.It Fn svc_dg_enablecache +This function allocates a duplicate request cache for the +service endpoint +.Fa xprt , +large enough to hold +.Fa cache_size +entries. +Once enabled, there is no way to disable caching. +This routine returns 0 if space necessary for a cache of the given size +was successfully allocated, and 1 otherwise. +.It Fn svc_exit +This function, when called by any of the RPC server procedure or +otherwise, causes +.Fn svc_run +to return. +.Pp +As currently implemented, +.Fn svc_exit +zeroes the +.Va svc_fdset +global variable. +If RPC server activity is to be resumed, +services must be reregistered with the RPC library +either through one of the +.Xr rpc_svc_create 3 +functions, or using +.Fn xprt_register . +The +.Fn svc_exit +function +has global scope and ends all RPC server activity. +.It Xo +.Vt fd_set Va svc_fdset +.Xc +A global variable reflecting the +RPC server's read file descriptor bit mask; it is suitable as an argument +to the +.Xr select 2 +system call. +This is only of interest +if service implementors do not call +.Fn svc_run , +but rather do their own asynchronous event processing. +This variable is read-only (do not pass its address to +.Xr select 2 ! ) , +yet it may change after calls to +.Fn svc_getreqset +or any creation routines. +.It Fn svc_freeargs +A function macro that frees any data allocated by the +RPC/XDR system when it decoded the arguments to a service procedure +using +.Fn svc_getargs . +This routine returns +.Dv TRUE +if the results were successfully +freed, and +.Dv FALSE +otherwise. +.It Fn svc_getargs +A function macro that decodes the arguments of an +RPC request associated with the RPC +service transport handle +.Fa xprt . +The +.Fa in +argument +is the address where the arguments will be placed; +.Fa inproc +is the XDR +routine used to decode the arguments. +This routine returns +.Dv TRUE +if decoding succeeds, and +.Dv FALSE +otherwise. +.It Fn svc_getreq_common +This routine is called to handle a request on the given +file descriptor. +.It Fn svc_getreq_poll +This routine is only of interest if a service implementor +does not call +.Fn svc_run , +but instead implements custom asynchronous event processing. +It is called when +.Xr poll 2 +has determined that an RPC request has arrived on some RPC +file descriptors; +.Fa pollretval +is the return value from +.Xr poll 2 +and +.Fa pfdp +is the array of +.Vt pollfd +structures on which the +.Xr poll 2 +was done. +It is assumed to be an array large enough to +contain the maximal number of descriptors allowed. +.It Fn svc_getreqset +This routine is only of interest if a service implementor +does not call +.Fn svc_run , +but instead implements custom asynchronous event processing. +It is called when +.Xr poll 2 +has determined that an RPC +request has arrived on some RPC file descriptors; +.Fa rdfds +is the resultant read file descriptor bit mask. +The routine returns when all file descriptors +associated with the value of +.Fa rdfds +have been serviced. +.It Fn svc_getrpccaller +The approved way of getting the network address of the caller +of a procedure associated with the +RPC service transport handle +.Fa xprt . +.It Fn __svc_getcallercreds +.Em Warning : +this macro is specific to +.Fx +and thus not portable. +This macro returns a pointer to a +.Vt cmsgcred +structure, defined in +.In sys/socket.h , +identifying the calling client. +This only works if the client is +calling the server over an +.Dv AF_LOCAL +socket. +.It Xo +.Vt struct pollfd Va svc_pollset[FD_SETSIZE] ; +.Xc +.Va svc_pollset +is an array of +.Vt pollfd +structures derived from +.Va svc_fdset[] . +It is suitable as an argument to the +.Xr poll 2 +system call. +The derivation of +.Va svc_pollset +from +.Va svc_fdset +is made in the current implementation in +.Fn svc_run . +Service implementors who do not call +.Fn svc_run +and who wish to use this array must perform this derivation themselves. +.It Fn svc_run +This routine never returns. +It waits for RPC +requests to arrive, and calls the appropriate service +procedure using +.Fn svc_getreq_poll +when one arrives. +This procedure is usually waiting for the +.Xr poll 2 +system call to return. +.It Fn svc_sendreply +Called by an RPC service's dispatch routine to send the results of a +remote procedure call. +The +.Fa xprt +argument +is the request's associated transport handle; +.Fa outproc +is the XDR +routine which is used to encode the results; and +.Fa out +is the address of the results. +This routine returns +.Dv TRUE +if it succeeds, +.Dv FALSE +otherwise. +.El +.Sh SEE ALSO +.Xr poll 2 , +.Xr select 2 , +.Xr rpc 3 , +.Xr rpc_svc_create 3 , +.Xr rpc_svc_err 3 , +.Xr rpc_svc_reg 3 diff --git a/lib/libc/rpc/rpc_svc_create.3 b/lib/libc/rpc/rpc_svc_create.3 new file mode 100644 index 0000000000..1c495f110e --- /dev/null +++ b/lib/libc/rpc/rpc_svc_create.3 @@ -0,0 +1,338 @@ +.\" @(#)rpc_svc_create.3n 1.26 93/08/26 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_svc_create 1.3 89/06/28 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_create.3,v 1.7 2003/09/08 19:57:15 ru Exp $ +.\" $DragonFly$ +.Dd May 3, 1993 +.Dt RPC_SVC_CREATE 3 +.Os +.Sh NAME +.Nm rpc_svc_create , +.Nm svc_control , +.Nm svc_create , +.Nm svc_destroy , +.Nm svc_dg_create , +.Nm svc_fd_create , +.Nm svc_raw_create , +.Nm svc_tli_create , +.Nm svc_tp_create , +.Nm svc_vc_create +.Nd library routines for the creation of server handles +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft bool_t +.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info" +.Ft int +.Fn svc_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" +.Ft SVCXPRT * +.Fn svc_dg_create "const int fildes" "const u_int sendsz" "const u_int recvsz" +.Ft void +.Fn svc_destroy "SVCXPRT *xprt" +.Ft "SVCXPRT *" +.Fn svc_fd_create "const int fildes" "const u_int sendsz" "const u_int recvsz" +.Ft "SVCXPRT *" +.Fn svc_raw_create "void" +.Ft "SVCXPRT *" +.Fn svc_tli_create "const int fildes" "const struct netconfig *netconf" "const struct t_bind *bindaddr" "const u_int sendsz" "const u_int recvsz" +.Ft "SVCXPRT *" +.Fn svc_tp_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" +.Ft "SVCXPRT *" +.Fn svc_vc_create "const int fildes" "const u_int sendsz" "const u_int recvsz" +.Sh DESCRIPTION +These routines are part of the RPC +library which allows C language programs to make procedure +calls on servers across the network. +These routines deal with the creation of service handles. +Once the handle is created, the server can be invoked by calling +.Fn svc_run . +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt SVCXPRT +data structure. +.Bl -tag -width XXXXX +.It Fn svc_control +A function to change or retrieve various information +about a service object. +The +.Fa req +argument +indicates the type of operation and +.Fa info +is a pointer to the information. +The supported values of +.Fa req , +their argument types, and what they do are: +.Bl -tag -width SVCGET_XID +.It Dv SVCGET_VERSQUIET +If a request is received for a program number +served by this server but the version number +is outside the range registered with the server, +an +.Dv RPC_PROGVERSMISMATCH +error will normally +be returned. +The +.Fa info +argument +should be a pointer to an +integer. +Upon successful completion of the +.Dv SVCGET_VERSQUIET +request, +.Fa *info +contains an +integer which describes the server's current +behavior: 0 indicates normal server behavior +(that is, an +.Dv RPC_PROGVERSMISMATCH +error +will be returned); 1 indicates that the out of +range request will be silently ignored. +.It Dv SVCSET_VERSQUIET +If a request is received for a program number +served by this server but the version number +is outside the range registered with the server, +an +.Dv RPC_PROGVERSMISMATCH +error will normally +be returned. +It is sometimes desirable to +change this behavior. +The +.Fa info +argument +should be a +pointer to an integer which is either 0 +(indicating normal server behavior - an +.Dv RPC_PROGVERSMISMATCH +error will be returned), +or 1 (indicating that the out of range request +should be silently ignored). +.El +.It Fn svc_create +The +.Fn svc_create +function +creates server handles for all the transports +belonging to the class +.Fa nettype . +The +.Fa nettype +argument +defines a class of transports which can be used +for a particular application. +The transports are tried in left to right order in +.Ev NETPATH +variable or in top to bottom order in the netconfig database. +If +.Fa nettype +is +.Dv NULL , +it defaults to +.Qq netpath . +.Pp +The +.Fn svc_create +function +registers itself with the rpcbind +service (see +.Xr rpcbind 8 ) . +The +.Fa dispatch +function +is called when there is a remote procedure call for the given +.Fa prognum +and +.Fa versnum ; +this requires calling +.Fn svc_run +(see +.Fn svc_run +in +.Xr rpc_svc_reg 3 ) . +If +.Fn svc_create +succeeds, it returns the number of server +handles it created, +otherwise it returns 0 and an error message is logged. +.It Fn svc_destroy +A function macro that destroys the RPC +service handle +.Fa xprt . +Destruction usually involves deallocation +of private data structures, +including +.Fa xprt +itself. +Use of +.Fa xprt +is undefined after calling this routine. +.It Fn svc_dg_create +This routine creates a connectionless RPC +service handle, and returns a pointer to it. +This routine returns +.Dv NULL +if it fails, and an error message is logged. +The +.Fa sendsz +and +.Fa recvsz +arguments +are arguments used to specify the size of the buffers. +If they are 0, suitable defaults are chosen. +The file descriptor +.Fa fildes +should be open and bound. +The server is not registered with +.Xr rpcbind 8 . +.Pp +Warning: +since connectionless-based RPC +messages can only hold limited amount of encoded data, +this transport cannot be used for procedures +that take large arguments or return huge results. +.It Fn svc_fd_create +This routine creates a service on top of an open and bound file descriptor, +and returns the handle to it. +Typically, this descriptor is a connected file descriptor for a +connection-oriented transport. +The +.Fa sendsz +and +.Fa recvsz +arguments +indicate sizes for the send and receive buffers. +If they are 0, reasonable defaults are chosen. +This routine returns +.Dv NULL +if it fails, and an error message is logged. +.It Fn svc_raw_create +This routine creates an RPC +service handle and returns a pointer to it. +The transport is really a buffer within the process's +address space, so the corresponding RPC +client should live in the same address space; +(see +.Fn clnt_raw_create +in +.Xr rpc_clnt_create 3 ) . +This routine allows simulation of RPC and acquisition of +RPC overheads (such as round trip times), +without any kernel and networking interference. +This routine returns +.Dv NULL +if it fails, and an error message is logged. +.Pp +Note: +.Fn svc_run +should not be called when the raw interface is being used. +.It Fn svc_tli_create +This routine creates an RPC +server handle, and returns a pointer to it. +The +.Fa fildes +argument +is the file descriptor on which the service is listening. +If +.Fa fildes +is +.Dv RPC_ANYFD , +it opens a file descriptor on the transport specified by +.Fa netconf . +If the file descriptor is unbound and +.Fa bindaddr +is not +.Dv NULL , +.Fa fildes +is bound to the address specified by +.Fa bindaddr , +otherwise +.Fa fildes +is bound to a default address chosen by the transport. +.Pp +Note: the +.Vt t_bind +structure comes from the TLI/XTI SysV interface, which +.Nx +does not use. +The structure is defined in +.In rpc/types.h +for compatibility as: +.Bd -literal +struct t_bind { + struct netbuf addr; /* network address, see rpc(3) */ + unsigned int qlen; /* queue length (for listen(2)) */ +}; +.Ed +.Pp +In the case where the default address is chosen, +the number of outstanding connect requests is set to 8 +for connection-oriented transports. +The user may specify the size of the send and receive buffers +with the arguments +.Fa sendsz +and +.Fa recvsz ; +values of 0 choose suitable defaults. +This routine returns +.Dv NULL +if it fails, +and an error message is logged. +The server is not registered with the +.Xr rpcbind 8 +service. +.It Fn svc_tp_create +The +.Fn svc_tp_create +function +creates a server handle for the network +specified by +.Fa netconf , +and registers itself with the rpcbind service. +The +.Fa dispatch +function +is called when there is a remote procedure call +for the given +.Fa prognum +and +.Fa versnum ; +this requires calling +.Fn svc_run . +The +.Fn svc_tp_create +function +returns the service handle if it succeeds, +otherwise a +.Dv NULL +is returned and an error message is logged. +.It Fn svc_vc_create +This routine creates a connection-oriented RPC +service and returns a pointer to it. +This routine returns +.Dv NULL +if it fails, and an error message is logged. +The users may specify the size of the send and receive buffers +with the arguments +.Fa sendsz +and +.Fa recvsz ; +values of 0 choose suitable defaults. +The file descriptor +.Fa fildes +should be open and bound. +The server is not registered with the +.Xr rpcbind 8 +service. +.El +.Sh SEE ALSO +.Xr rpc 3 , +.Xr rpc_svc_calls 3 , +.Xr rpc_svc_err 3 , +.Xr rpc_svc_reg 3 , +.Xr rpcbind 8 diff --git a/lib/libc/rpc/rpc_svc_err.3 b/lib/libc/rpc/rpc_svc_err.3 new file mode 100644 index 0000000000..8230e23115 --- /dev/null +++ b/lib/libc/rpc/rpc_svc_err.3 @@ -0,0 +1,98 @@ +.\" @(#)rpc_svc_err.3n 1.23 93/08/31 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_svc_err 1.4 89/06/28 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $NetBSD: rpc_svc_err.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_err.3,v 1.5 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 3, 1993 +.Dt RPC_SVC_ERR 3 +.Os +.Sh NAME +.Nm rpc_svc_err , +.Nm svcerr_auth , +.Nm svcerr_decode , +.Nm svcerr_noproc , +.Nm svcerr_noprog , +.Nm svcerr_progvers , +.Nm svcerr_systemerr , +.Nm svcerr_weakauth +.Nd library routines for server side remote procedure call errors +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft void +.Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why" +.Ft void +.Fn svcerr_decode "SVCXPRT *xprt" +.Ft void +.Fn svcerr_noproc "SVCXPRT *xprt" +.Ft void +.Fn svcerr_noprog "SVCXPRT *xprt" +.Ft void +.Fn svcerr_progvers "SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers" +.Ft void +.Fn svcerr_systemerr "SVCXPRT *xprt" +.Ft void +.Fn svcerr_weakauth "SVCXPRT *xprt" +.Sh DESCRIPTION +These routines are part of the RPC +library which allows C language programs to make procedure +calls on other machines across the network. +.Pp +These routines can be called by the server side +dispatch function if there is any error in the +transaction with the client. +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt SVCXPRT +data structure. +.Bl -tag -width XXXXX +.It Fn svcerr_auth +Called by a service dispatch routine that refuses to perform +a remote procedure call due to an authentication error. +.It Fn svcerr_decode +Called by a service dispatch routine that cannot successfully +decode the remote arguments +(see +.Fn svc_getargs +in +.Xr rpc_svc_reg 3 ) . +.It Fn svcerr_noproc +Called by a service dispatch routine that does not implement +the procedure number that the caller requests. +.It Fn svcerr_noprog +Called when the desired program is not registered with the +RPC package. +Service implementors usually do not need this routine. +.It Fn svcerr_progvers +Called when the desired version of a program is not registered with the +RPC package. +The +.Fa low_vers +argument +is the lowest version number, +and +.Fa high_vers +is the highest version number. +Service implementors usually do not need this routine. +.It Fn svcerr_systemerr +Called by a service dispatch routine when it detects a system +error not covered by any particular protocol. +For example, if a service can no longer allocate storage, +it may call this routine. +.It Fn svcerr_weakauth +Called by a service dispatch routine that refuses to perform +a remote procedure call due to insufficient (but correct) +authentication arguments. +The routine calls +.Fn svcerr_auth "xprt" "AUTH_TOOWEAK" . +.El +.Sh SEE ALSO +.Xr rpc 3 , +.Xr rpc_svc_calls 3 , +.Xr rpc_svc_create 3 , +.Xr rpc_svc_reg 3 diff --git a/lib/libc/rpc/rpc_svc_reg.3 b/lib/libc/rpc/rpc_svc_reg.3 new file mode 100644 index 0000000000..a005e70de2 --- /dev/null +++ b/lib/libc/rpc/rpc_svc_reg.3 @@ -0,0 +1,184 @@ +.\" @(#)rpc_svc_reg.3n 1.32 93/08/31 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_svc_call 1.6 89/07/20 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $NetBSD: rpc_svc_reg.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpc_svc_reg.3,v 1.6 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 3, 1993 +.Dt RPC_SVC_REG 3 +.Os +.Sh NAME +.Nm rpc_svc_reg , +.Nm rpc_reg , +.Nm svc_reg , +.Nm svc_unreg , +.Nm svc_auth_reg , +.Nm xprt_register , +.Nm xprt_unregister +.Nd library routines for registering servers +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft int +.Fn rpc_reg "rpcprog_t prognum" "rpcvers_t versnum" "rpcproc_t procnum" "char *(*procname)()" "xdrproc_t inproc" "xdrproc_t outproc" "char *nettype" +.Ft bool_t +.Fn svc_reg "SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const struct netconfig *netconf" +.Ft void +.Fn svc_unreg "const rpcprog_t prognum" "const rpcvers_t versnum" +.Ft int +.Fn svc_auth_reg "int cred_flavor" "enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)" +.Ft void +.Fn xprt_register "SVCXPRT *xprt" +.Ft void +.Fn xprt_unregister "SVCXPRT *xprt" +.Sh DESCRIPTION +These routines are a part of the RPC +library which allows the RPC +servers to register themselves with rpcbind +(see +.Xr rpcbind 8 ) , +and associate the given program and version +number with the dispatch function. +When the RPC server receives a RPC request, the library invokes the +dispatch routine with the appropriate arguments. +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt SVCXPRT +data structure. +.Bl -tag -width XXXXX +.It Fn rpc_reg +Register program +.Fa prognum , +procedure +.Fa procname , +and version +.Fa versnum +with the RPC +service package. +If a request arrives for program +.Fa prognum , +version +.Fa versnum , +and procedure +.Fa procnum , +.Fa procname +is called with a pointer to its argument(s); +.Fa procname +should return a pointer to its static result(s); +.Fa inproc +is the XDR function used to decode the arguments while +.Fa outproc +is the XDR function used to encode the results. +Procedures are registered on all available transports of the class +.Fa nettype . +See +.Xr rpc 3 . +This routine returns 0 if the registration succeeded, +\-1 otherwise. +.It Fn svc_reg +Associates +.Fa prognum +and +.Fa versnum +with the service dispatch procedure, +.Fa dispatch . +If +.Fa netconf +is +.Dv NULL , +the service is not registered with the +.Xr rpcbind 8 +service. +If +.Fa netconf +is non-zero, +then a mapping of the triple +.Bq Fa prognum , versnum , netconf->nc_netid +to +.Fa xprt->xp_ltaddr +is established with the local rpcbind +service. +.Pp +The +.Fn svc_reg +routine returns 1 if it succeeds, +and 0 otherwise. +.It Fn svc_unreg +Remove from the rpcbind +service, all mappings of the triple +.Bq Fa prognum , versnum , No all-transports +to network address +and all mappings within the RPC service package +of the double +.Bq Fa prognum , versnum +to dispatch routines. +.It Fn svc_auth_reg +Registers the service authentication routine +.Fa handler +with the dispatch mechanism so that it can be +invoked to authenticate RPC requests received +with authentication type +.Fa cred_flavor . +This interface allows developers to add new authentication +types to their RPC applications without needing to modify +the libraries. +Service implementors usually do not need this routine. +.Pp +Typical service application would call +.Fn svc_auth_reg +after registering the service and prior to calling +.Fn svc_run . +When needed to process an RPC credential of type +.Fa cred_flavor , +the +.Fa handler +procedure will be called with two arguments, +.Fa "struct svc_req *rqst" +and +.Fa "struct rpc_msg *msg" , +and is expected to return a valid +.Vt "enum auth_stat" +value. +There is no provision to change or delete an authentication handler +once registered. +.Pp +The +.Fn svc_auth_reg +routine returns 0 if the registration is successful, +1 if +.Fa cred_flavor +already has an authentication handler registered for it, +and \-1 otherwise. +.It Fn xprt_register +After RPC service transport handle +.Fa xprt +is created, it is registered with the RPC +service package. +This routine modifies the global variable +.Va svc_fdset +(see +.Xr rpc_svc_calls 3 ) . +Service implementors usually do not need this routine. +.It Fn xprt_unregister +Before an RPC service transport handle +.Fa xprt +is destroyed, it unregisters itself with the +RPC service package. +This routine modifies the global variable +.Va svc_fdset +(see +.Xr rpc_svc_calls 3 ) . +Service implementors usually do not need this routine. +.El +.Sh SEE ALSO +.Xr select 2 , +.Xr rpc 3 , +.Xr rpcbind 3 , +.Xr rpc_svc_calls 3 , +.Xr rpc_svc_create 3 , +.Xr rpc_svc_err 3 , +.Xr rpcbind 8 diff --git a/lib/libc/rpc/rpc_xdr.3 b/lib/libc/rpc/rpc_xdr.3 new file mode 100644 index 0000000000..20d8a09673 --- /dev/null +++ b/lib/libc/rpc/rpc_xdr.3 @@ -0,0 +1,102 @@ +.\" @(#)rpc_xdr.3n 1.24 93/08/31 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" @(#)rpc_xdr.new 1.1 89/04/06 SMI; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" $FreeBSD: src/lib/libc/rpc/rpc_xdr.3,v 1.4 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 3, 1993 +.Dt RPC_XDR 3 +.Os +.Sh NAME +.Nm xdr_accepted_reply , +.Nm xdr_authsys_parms , +.Nm xdr_callhdr , +.Nm xdr_callmsg , +.Nm xdr_opaque_auth , +.Nm xdr_rejected_reply , +.Nm xdr_replymsg +.Nd XDR library routines for remote procedure calls +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft bool_t +.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar" +.Ft bool_t +.Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp" +.Ft bool_t +.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr" +.Ft bool_t +.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg" +.Ft bool_t +.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap" +.Ft bool_t +.Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr" +.Ft bool_t +.Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg" +.Sh DESCRIPTION +These routines are used for describing the +RPC messages in XDR language. +They should normally be used by those who do not +want to use the RPC +package directly. +These routines return +.Dv TRUE +if they succeed, +.Dv FALSE +otherwise. +.Sh Routines +See +.Xr rpc 3 +for the definition of the +.Vt XDR +data structure. +.Bl -tag -width XXXXX +.It Fn xdr_accepted_reply +Used to translate between RPC +reply messages and their external representation. +It includes the status of the RPC +call in the XDR language format. +In the case of success, it also includes the call results. +.It Fn xdr_authsys_parms +Used for describing +.Ux +operating system credentials. +It includes machine-name, uid, gid list, etc. +.It Fn xdr_callhdr +Used for describing +RPC +call header messages. +It encodes the static part of the call message header in the +XDR language format. +It includes information such as transaction +ID, RPC version number, program and version number. +.It Fn xdr_callmsg +Used for describing +RPC call messages. +This includes all the RPC +call information such as transaction +ID, RPC version number, program number, version number, +authentication information, etc. +This is normally used by servers to determine information about the client +RPC call. +.It Fn xdr_opaque_auth +Used for describing RPC +opaque authentication information messages. +.It Fn xdr_rejected_reply +Used for describing RPC reply messages. +It encodes the rejected RPC message in the XDR language format. +The message could be rejected either because of version +number mis-match or because of authentication errors. +.It Fn xdr_replymsg +Used for describing RPC +reply messages. +It translates between the +RPC reply message and its external representation. +This reply could be either an acceptance, +rejection or +.Dv NULL . +.El +.Sh SEE ALSO +.Xr rpc 3 , +.Xr xdr 3 diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c new file mode 100644 index 0000000000..6461d1a253 --- /dev/null +++ b/lib/libc/rpc/rpcb_clnt.c @@ -0,0 +1,1318 @@ +/* + * The contents of this file are subject to the Sun Standards + * License Version 1.0 the (the "License";) You may not use + * this file except in compliance with the License. You may + * obtain a copy of the License at lib/libc/rpc/LICENSE + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is Copyright 1998 by Sun Microsystems, Inc + * + * The Initial Developer of the Original Code is: Sun + * Microsystems, Inc. + * + * All Rights Reserved. + * + * 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 + * @(#)rpcb_clnt.c 1.27 94/04/24 SMI; 1.30 89/06/21 Copyr 1988 Sun Micro + * $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ + * $FreeBSD: src/lib/libc/rpc/rpcb_clnt.c,v 1.17 2007/09/20 22:35:24 matteo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * rpcb_clnt.c + * interface to rpcbind rpc service. + * + * Copyright (C) 1988, Sun Microsystems, Inc. + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include /* FOR IPPROTO_TCP/UDP definitions */ +#include +#endif /* PORTMAP */ +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + +#include "rpc_com.h" +#include "mt_misc.h" + +static struct timeval tottimeout = { 60, 0 }; +static const struct timeval rmttimeout = { 3, 0 }; +static struct timeval rpcbrmttime = { 15, 0 }; + +extern bool_t xdr_wrapstring(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(const char *, const char *); +static void delete_cache(struct netbuf *); +static void add_cache(const char *, const char *, struct netbuf *, char *); +static CLIENT *getclnthandle(const char *, const struct netconfig *, char **); +static CLIENT *local_rpcb(void); +static struct netbuf *got_entry(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(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. + */ + +/* + * The routines check_cache(), add_cache(), delete_cache() manage the + * cache of rpcbind addresses for (host, netid). + */ + +static struct address_cache * +check_cache(const char *host, const char *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(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(const char *host, const char *netid, struct netbuf *taddr, + char *uaddr) +{ + 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)) { + goto out; + } + 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) { +out: + if (ad_cache->ac_host) + free(ad_cache->ac_host); + if (ad_cache->ac_netid) + free(ad_cache->ac_netid); + if (ad_cache->ac_uaddr) + free(ad_cache->ac_uaddr); + if (ad_cache->ac_taddr) + free(ad_cache->ac_taddr); + free(ad_cache); + 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. If targaddr is non-NULL, the "universal address" of the + * host will be stored in *targaddr; the caller is responsible for + * freeing this string. + * On error, returns NULL and free's everything. + */ +static CLIENT * +getclnthandle(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 */ + client = NULL; + addr_to_delete.len = 0; + rwlock_rdlock(&rpcbaddr_cache_lock); + ad_cache = NULL; + if (host != NULL) + 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 = strdup(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 (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { + client = local_rpcb(); + if (! client) { +#ifdef ND_DEBUG + clnt_pcreateerror("rpcbind clnt interface"); +#endif + return (NULL); + } else { + struct sockaddr_un sun; + if (targaddr) { + *targaddr = malloc(sizeof(sun.sun_path)); + if (*targaddr == NULL) { + CLNT_DESTROY(client); + return (NULL); + } + strncpy(*targaddr, _PATH_RPCBINDSOCK, + sizeof(sun.sun_path)); + } + return (client); + } + } else { + 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; + } + } + if (res) + 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(void) +{ + CLIENT *client; + static struct netconfig *loopnconf; + static char *hostname; + 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) { + /* Mark the socket to be closed in destructor */ + CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); + return client; + } + + /* Nobody needs this socket anymore; free the descriptor. */ + _close(sock); + +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(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) { + CLNT_DESTROY(client); + 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. + */ + 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(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]; + 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(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] != 0)) { + 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); +} + +/* + * Quick check to see if rpcbind is up. Tries to connect over + * local transport. + */ +static bool_t +__rpcbind_is_up(void) +{ + struct netconfig *nconf; + struct sockaddr_un sun; + void *localhandle; + int sock; + + nconf = NULL; + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } + if (nconf == NULL) + return (FALSE); + + endnetconfig(localhandle); + + memset(&sun, 0, sizeof sun); + sock = _socket(AF_LOCAL, SOCK_STREAM, 0); + if (sock < 0) + return (FALSE); + sun.sun_family = AF_LOCAL; + strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); + sun.sun_len = SUN_LEN(&sun); + + if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) { + _close(sock); + return (FALSE); + } + + _close(sock); + return (TRUE); +} + +/* + * 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_timed(rpcprog_t program, rpcvers_t version, + const struct netconfig *nconf, const char *host, + CLIENT **clpp, struct timeval *tp) +{ + static bool_t check_rpcbind = TRUE; + 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; + + /* + * Use default total timeout if no timeout is specified. + */ + if (tp == NULL) + tp = &tottimeout; + +#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 version and retry timeout. + */ + CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); + CLNT_CONTROL(client, CLSET_VERS, (char *)&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, + *tp); + 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 *)&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: + /* + * Check if rpcbind is up. This prevents needless delays when + * accessing applications such as the keyserver while booting + * disklessly. + */ + if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { + if (!__rpcbind_is_up()) { + rpc_createerr.cf_stat = RPC_PMAPFAILURE; + rpc_createerr.cf_error.re_errno = 0; + goto error; + } + check_rpcbind = FALSE; + } + + /* + * 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. + */ + if (nconf->nc_semantics == NC_TPI_COTS_ORD || + nconf->nc_semantics == NC_TPI_COTS) { + + 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 ((handle = __rpc_setconf("datagram_v")) != NULL) { + 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_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); + + 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, *tp); + if (clnt_st == RPC_SUCCESS) { + if ((address = got_entry(relp, nconf)) != NULL) { + xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, + (char *)(void *)&relp); + CLNT_CONTROL(client, CLGET_SVC_ADDR, + (char *)(void *)&servaddr); + __rpc_fixup_addr(address, &servaddr); + 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 (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || + (nconf->nc_semantics == NC_TPI_COTS))) { + /* 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) */ + + CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime); + 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, *tp); + if (clnt_st == RPC_SUCCESS) { + if ((ua == NULL) || (ua[0] == 0)) { + /* 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; + } + } + +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); + } + if (parms.r_addr != NULL && parms.r_addr != nullstring) + free(parms.r_addr); + 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(rpcprog_t program, rpcvers_t version, + const struct netconfig *nconf, struct netbuf *address, + const char *host) +{ + struct netbuf *na; + + if ((na = __rpcb_findaddr_timed(program, version, + (struct netconfig *) nconf, (char *) host, + (CLIENT **) NULL, (struct timeval *) 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(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(const struct netconfig *nconf, const char *host, rpcprog_t prog, + rpcvers_t vers, rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, + xdrproc_t xdrres, caddr_t resp, struct timeval tout, + const struct netbuf *addr_ptr) +{ + CLIENT *client; + enum clnt_stat stat; + struct r_rpcb_rmtcallargs a; + struct r_rpcb_rmtcallres r; + rpcvers_t rpcb_vers; + + stat = 0; + 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(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] == 0)) { + 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(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(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 0000000000..dfb83fb78a --- /dev/null +++ b/lib/libc/rpc/rpcb_prot.c @@ -0,0 +1,311 @@ +/* + * 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 + * + * @(#)rpcb_prot.c 1.13 94/04/24 SMI; 1.9 89/04/21 Copyr 1984 Sun Micro + * $NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/rpcb_prot.c,v 1.7 2007/11/20 01:51:20 jb Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * rpcb_prot.c + * XDR routines for the rpcbinder version 3. + * + * Copyright (C) 1984, 1988, Sun Microsystems, Inc. + */ + +#include "namespace.h" +#include +#include +#include +#include +#include "un-namespace.h" + +bool_t +xdr_rpcb(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(XDR *xdrs, rpcblist_ptr *rp) +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + int freeing = (xdrs->x_op == XDR_FREE); + rpcblist_ptr next; + rpcblist_ptr next_copy; + + next = NULL; + for (;;) { + more_elements = (bool_t)(*rp != NULL); + if (! xdr_bool(xdrs, &more_elements)) { + return (FALSE); + } + if (! more_elements) { + return (TRUE); /* we are done */ + } + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing && *rp) + 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 if (*rp) { + 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(XDR *xdrs, RPCBLIST **rp) +{ + bool_t dummy; + + dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp); + return (dummy); +} + + +bool_t +xdr_rpcb_entry(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(XDR *xdrs, rpcb_entry_list_ptr *rp) +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + int freeing = (xdrs->x_op == XDR_FREE); + rpcb_entry_list_ptr next; + rpcb_entry_list_ptr next_copy; + + next = NULL; + for (;;) { + more_elements = (bool_t)(*rp != NULL); + if (! xdr_bool(xdrs, &more_elements)) { + return (FALSE); + } + if (! more_elements) { + return (TRUE); /* we are done */ + } + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing) + next = (*rp)->rpcb_entry_next; + if (! xdr_reference(xdrs, (caddr_t *)rp, + (u_int)sizeof (rpcb_entry_list), + (xdrproc_t)xdr_rpcb_entry)) { + return (FALSE); + } + if (freeing && *rp) { + 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 if (*rp) { + rp = &((*rp)->rpcb_entry_next); + } + } + /*NOTREACHED*/ +} + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rpcb_rmtcallargs(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(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(XDR *xdrs, struct netbuf *objp) +{ + bool_t dummy; + void **pp; + + if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) { + return (FALSE); + } + pp = &objp->buf; + dummy = xdr_bytes(xdrs, (char **) pp, + (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 0000000000..52ef33340e --- /dev/null +++ b/lib/libc/rpc/rpcb_st_xdr.c @@ -0,0 +1,260 @@ +/* + * 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 + * + * $NetBSD: rpcb_st_xdr.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/rpcb_st_xdr.c,v 1.4 2007/11/20 01:51:20 jb Exp $ + * $DragonFly$ + */ +/* + * 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 +#include "un-namespace.h" + +/* Link list of all the stats about getport and getaddr */ + +bool_t +xdr_rpcbs_addrlist(XDR *xdrs, rpcbs_addrlist *objp) +{ + struct rpcbs_addrlist **pnext; + + 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); + } + + pnext = &objp->next; + + if (!xdr_pointer(xdrs, (char **) pnext, + 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(XDR *xdrs, rpcbs_rmtcalllist *objp) +{ + int32_t *buf; + struct rpcbs_rmtcalllist **pnext; + + 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); + } + pnext = &objp->next; + if (!xdr_pointer(xdrs, (char **) pnext, + 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 **) pnext, + 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 **) pnext, + sizeof (rpcbs_rmtcalllist), + (xdrproc_t)xdr_rpcbs_rmtcalllist)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_rpcbs_proc(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(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(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(XDR *xdrs, rpcb_stat *objp) +{ + + if (!xdr_rpcbs_proc(xdrs, objp->info)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->setinfo)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->unsetinfo)) { + return (FALSE); + } + if (!xdr_rpcbs_addrlist_ptr(xdrs, &objp->addrinfo)) { + return (FALSE); + } + if (!xdr_rpcbs_rmtcalllist_ptr(xdrs, &objp->rmtinfo)) { + return (FALSE); + } + return (TRUE); +} + +/* + * One rpcb_stat structure is returned for each version of rpcbind + * being monitored. + */ +bool_t +xdr_rpcb_stat_byvers(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 0000000000..4443e5b0a0 --- /dev/null +++ b/lib/libc/rpc/rpcbind.3 @@ -0,0 +1,195 @@ +.\" @(#)rpcbind.3n 1.25 93/05/07 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" Copyright (c) 1988 Sun Microsystem's, Inc. - All Right's Reserved. +.\" $NetBSD: rpcbind.3,v 1.2 2000/06/03 18:47:28 fvdl Exp $ +.\" $FreeBSD: src/lib/libc/rpc/rpcbind.3,v 1.6 2005/02/09 18:03:14 ru Exp $ +.\" $DragonFly$ +.Dd May 7, 1993 +.Dt RPCBIND 3 +.Os +.Sh NAME +.Nm rpcb_getmaps , +.Nm rpcb_getaddr , +.Nm rpcb_gettime , +.Nm rpcb_rmtcall , +.Nm rpcb_set , +.Nm rpcb_unset +.Nd library routines for RPC bind service +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/rpc.h +.Ft "rpcblist *" +.Fn rpcb_getmaps "const struct netconfig *netconf" "const char *host" +.Ft bool_t +.Fn rpcb_getaddr "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const char *host" +.Ft bool_t +.Fn rpcb_gettime "const char *host" "time_t * timep" +.Ft "enum clnt_stat" +.Fn rpcb_rmtcall "const struct netconfig *netconf" "const char *host" "const rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "const caddr_t out" "const struct timeval tout, const struct netbuf *svcaddr" +.Ft bool_t +.Fn rpcb_set "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct netbuf *svcaddr" +.Ft bool_t +.Fn rpcb_unset "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" +.Sh DESCRIPTION +These routines allow client C programs to make procedure +calls to the RPC binder service. +(see +.Xr rpcbind 8 ) +maintains a list of mappings between programs +and their universal addresses. +.Sh Routines +.Bl -tag -width XXXXX +.It Fn rpcb_getmaps +An interface to the rpcbind service, +which returns a list of the current +RPC program-to-address mappings on +.Fa host . +It uses the transport specified through +.Fa netconf +to contact the remote rpcbind +service on +.Fa host . +This routine will return +.Dv NULL , +if the remote rpcbind could not be contacted. +.It Fn rpcb_getaddr +An interface to the rpcbind +service, which finds the address of the service on +.Fa host +that is registered with program number +.Fa prognum , +version +.Fa versnum , +and speaks the transport protocol associated with +.Fa netconf . +The address found is returned in +.Fa svcaddr . +The +.Fa svcaddr +argument +should be preallocated. +This routine returns +.Dv TRUE +if it succeeds. +A return value of +.Dv FALSE +means that the mapping does not exist +or that the RPC +system failed to contact the remote +rpcbind service. +In the latter case, the global variable +.Va rpc_createerr +(see +.Xr rpc_clnt_create 3 ) +contains the +RPC status. +.It Fn rpcb_gettime +This routine returns the time on +.Fa host +in +.Fa timep . +If +.Fa host +is +.Dv NULL , +.Fn rpcb_gettime +returns the time on its own machine. +This routine returns +.Dv TRUE +if it succeeds, +.Dv FALSE +if it fails. +The +.Fn rpcb_gettime +function +can be used to synchronize the time between the +client and the remote server. +.It Fn rpcb_rmtcall +An interface to the rpcbind service, which instructs +rpcbind on +.Fa host +to make an RPC +call on your behalf to a procedure on that host. +The +.Fn netconfig +structure should correspond to a connectionless transport. +The +.Fa svcaddr +argument +will be modified to the server's address if the procedure succeeds +(see +.Fn rpc_call +and +.Fn clnt_call +in +.Xr rpc_clnt_calls 3 +for the definitions of other arguments). +.Pp +This procedure should normally be used for a +.Dq ping +and nothing else. +This routine allows programs to do lookup and call, all in one step. +.Pp +Note: Even if the server is not running +.Fn rpcb_rmtcall +does not return any error messages to the caller. +In such a case, the caller times out. +.Pp +Note: +.Fn rpcb_rmtcall +is only available for connectionless transports. +.It Fn rpcb_set +An interface to the rpcbind +service, which establishes a mapping between the triple +.Bq Fa prognum , versnum , netconf->nc_netid +and +.Fa svcaddr +on the machine's rpcbind +service. +The value of +.Fa nc_netid +must correspond to a network identifier that is defined by the +netconfig database. +This routine returns +.Dv TRUE +if it succeeds, +.Dv FALSE +otherwise. +(See also +.Fn svc_reg +in +.Xr rpc_svc_calls 3 . ) +If there already exists such an entry with rpcbind, +.Fn rpcb_set +will fail. +.It Fn rpcb_unset +An interface to the rpcbind +service, which destroys the mapping between the triple +.Bq Fa prognum , versnum , netconf->nc_netid +and the address on the machine's rpcbind +service. +If +.Fa netconf +is +.Dv NULL , +.Fn rpcb_unset +destroys all mapping between the triple +.Bq Fa prognum , versnum , No all-transports +and the addresses on the machine's rpcbind service. +This routine returns +.Dv TRUE +if it succeeds, +.Dv FALSE +otherwise. +Only the owner of the service or the super-user can destroy the mapping. +(See also +.Fn svc_unreg +in +.Xr rpc_svc_calls 3 . ) +.El +.Sh SEE ALSO +.Xr rpc_clnt_calls 3 , +.Xr rpc_svc_calls 3 , +.Xr rpcbind 8 , +.Xr rpcinfo 8 diff --git a/lib/libc/rpc/rpcdname.c b/lib/libc/rpc/rpcdname.c index 8d21ef56e4..7abb3dc3ef 100644 --- a/lib/libc/rpc/rpcdname.c +++ b/lib/libc/rpc/rpcdname.c @@ -28,6 +28,7 @@ * Mountain View, California 94043 * * @(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro + * $FreeBSD: src/lib/libc/rpc/rpcdname.c,v 1.5 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/rpcdname.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ */ @@ -36,9 +37,11 @@ * Gets the default domain name */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" static char *default_domain = 0; @@ -68,7 +71,7 @@ get_default_domain(void) * get rejected elsewhere in the NIS client package. */ int -_rpc_get_default_domain(char **domain) +__rpc_get_default_domain(char **domain) { if ((*domain = get_default_domain()) != 0) return (0); diff --git a/lib/libc/rpc/rtime.c b/lib/libc/rpc/rtime.c index d2bbe944f9..2a589a1e07 100644 --- a/lib/libc/rpc/rtime.c +++ b/lib/libc/rpc/rtime.c @@ -5,35 +5,34 @@ * 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 * * @(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI - * $FreeBSD: src/lib/libc/rpc/rtime.c,v 1.5 2000/01/27 23:06:41 jasone Exp $ + * $FreeBSD: src/lib/libc/rpc/rtime.c,v 1.9 2005/03/10 00:57:01 stefanf Exp $ * $DragonFly: src/lib/libc/rpc/rtime.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ */ /* * Copyright (c) 1988 by Sun Microsystems, Inc. - */ /* @@ -58,12 +57,12 @@ #include #include "un-namespace.h" -extern int _rpc_dtablesize ( void ); +extern int _rpc_dtablesize(void); #define NYEARS (unsigned long)(1970 - 1900) #define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4))) -static void do_close ( int ); +static void do_close(int); int rtime(struct sockaddr_in *addrp, struct timeval *timep, struct timeval *timeout) @@ -73,7 +72,7 @@ rtime(struct sockaddr_in *addrp, struct timeval *timep, struct timeval *timeout) int res; unsigned long thetime; struct sockaddr_in from; - int fromlen; + socklen_t fromlen; int type; struct servent *serv; diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index d3fa95fe35..2a321bb311 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -28,7 +28,8 @@ * * @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro * @(#)svc.c 2.4 88/08/11 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc.c,v 1.14.2.1 2001/03/05 10:50:36 obrien Exp $ + * $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc.c,v 1.24 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/svc.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -42,17 +43,29 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#include +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include #include +#include + #include +#ifdef PORTMAP #include +#endif /* PORTMAP */ +#include "un-namespace.h" -static SVCXPRT **xports; -static int xportssize; +#include "rpc_com.h" +#include "mt_misc.h" -#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) /* @@ -63,15 +76,15 @@ 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)(struct svc_req *, SVCXPRT *); } *svc_head; -static struct svc_callout *svc_find(); - -int __svc_fdsetsize = 0; -fd_set *__svc_fdset = NULL; +static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, + struct svc_callout **, char *); +static void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock); /* *************** SVCXPRT related stuff **************** */ @@ -81,97 +94,196 @@ fd_set *__svc_fdset = NULL; void xprt_register(SVCXPRT *xprt) { - 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; - if (sock < FD_SETSIZE) + assert(xprt != NULL); + + sock = xprt->xp_fd; + + rwlock_wrlock(&svc_fd_lock); + if (__svc_xports == NULL) { + __svc_xports = (SVCXPRT **) + mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); + if (__svc_xports == NULL) + return; + memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); + } + if (sock < FD_SETSIZE) { + __svc_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); +} + +void +xprt_unregister(SVCXPRT *xprt) +{ + __xprt_do_unregister(xprt, TRUE); +} + +void +__xprt_unregister_unlocked(SVCXPRT *xprt) +{ + __xprt_do_unregister(xprt, FALSE); } /* * De-activate a transport handle. */ -void -xprt_unregister(SVCXPRT *xprt) +static void +__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) { - 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--) - if (xports[svc_maxfd]) + int sock; + + assert(xprt != NULL); + + sock = xprt->xp_fd; + + if (dolock) + rwlock_wrlock(&svc_fd_lock); + if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) { + __svc_xports[sock] = NULL; + FD_CLR(sock, &svc_fdset); + if (sock >= svc_maxfd) { + for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--) + if (__svc_xports[svc_maxfd]) break; } - /* - * XXX could use svc_maxfd as a hint to - * decrease the size of __svc_fdset - */ } + if (dolock) + 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(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, + void (*dispatch)(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(const rpcprog_t prog, const rpcvers_t vers) +{ + struct svc_callout *prev; + struct svc_callout *s; + + /* unregister the information anyway */ + 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 * program number comes in. */ bool_t -svc_register(SVCXPRT *xprt, u_long prog, u_long vers, void (*dispatch)(), - int protocol) +svc_register(SVCXPRT *xprt, u_long prog, u_long vers, + void (*dispatch)(struct svc_req *, SVCXPRT *), int protocol) { struct svc_callout *prev; struct svc_callout *s; - if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) { + assert(xprt != NULL); + assert(dispatch != NULL); + + 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; @@ -192,35 +304,40 @@ svc_unregister(u_long prog, u_long vers) struct svc_callout *prev; 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 */ pmap_unset(prog, vers); } +#endif /* PORTMAP */ /* * Search the callout list for a program number, return the callout * struct. */ static struct svc_callout * -svc_find(u_long prog, u_long vers, struct svc_callout **prev) +svc_find(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid) { struct svc_callout *s, *p; - 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; + assert(prev != NULL); + + 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); } @@ -231,10 +348,12 @@ done: * Send a reply to an rpc request */ bool_t -svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, caddr_t xdr_location) +svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, void *xdr_location) { 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; @@ -252,6 +371,8 @@ svcerr_noproc(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; @@ -267,6 +388,8 @@ svcerr_decode(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; @@ -282,6 +405,8 @@ svcerr_systemerr(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; @@ -297,6 +422,8 @@ svcerr_auth(SVCXPRT *xprt, enum auth_stat 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; @@ -311,6 +438,8 @@ void svcerr_weakauth(SVCXPRT *xprt) { + assert(xprt != NULL); + svcerr_auth(xprt, AUTH_TOOWEAK); } @@ -322,6 +451,8 @@ svcerr_noprog(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; @@ -333,16 +464,18 @@ svcerr_noprog(SVCXPRT *xprt) * Program version mismatch error reply */ void -svcerr_progvers(SVCXPRT *xprt, u_long low_vers, u_long high_vers) +svcerr_progvers(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); } @@ -377,88 +510,160 @@ svc_getreq(int rdfds) void svc_getreqset(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(fd_set *readfds, int width) +svc_getreq_common(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; - SVCXPRT *xprt; - int bit; - int sock; - 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 */ - 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 = __svc_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 != __svc_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(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); + } + } +} + +bool_t +rpc_control(int what, void *arg) +{ + int val; + + switch (what) { + case RPC_SVC_CONNMAXREC_SET: + val = *(int *)arg; + if (val <= 0) + return FALSE; + __svc_maxrec = val; + return TRUE; + case RPC_SVC_CONNMAXREC_GET: + *(int *)arg = __svc_maxrec; + return TRUE; + default: + break; } + return FALSE; } diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c index d3bea32e77..bfbb3e0d44 100644 --- a/lib/libc/rpc/svc_auth.c +++ b/lib/libc/rpc/svc_auth.c @@ -5,56 +5,47 @@ * 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 * - * @(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro - * $FreeBSD: src/lib/libc/rpc/svc_auth.c,v 1.7 1999/12/29 05:04:16 peter Exp $ + * @(#)svc_auth.c 1.16 94/04/24 SMI; 1.26 89/02/07 Copyr 1984 Sun Micro + * $NetBSD: svc_auth.c,v 1.12 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_auth.c,v 1.13 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/svc_auth.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ /* - * Copyright (c) 1986-1991 by Sun Microsystems Inc. + * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ -#ident "@(#)svc_auth.c 1.16 94/04/24 SMI" - /* * svc_auth.c, Server-side rpc authenticator interface. - * */ -#ifdef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#endif +#include "namespace.h" +#include "reentrant.h" #include +#include +#include +#include "un-namespace.h" +#include "mt_misc.h" /* * svcauthsw is the bdevsw of server side authentication. @@ -71,15 +62,10 @@ * */ -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)(struct svc_req *, struct rpc_msg *); struct authsvc *next; }; static struct authsvc *Auths = NULL; @@ -107,6 +93,9 @@ _authenticate(struct svc_req *rqst, struct rpc_msg *msg) { int cred_flavor; struct authsvc *asp; + enum auth_stat dummy; + +/* 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; @@ -114,34 +103,35 @@ _authenticate(struct svc_req *rqst, struct rpc_msg *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); } @@ -168,13 +158,14 @@ _svcauth_null(struct svc_req *rqst, struct rpc_msg *msg) */ int -svc_auth_reg(int cred_flavor, enum auth_stat (*handler)()) +svc_auth_reg(int cred_flavor, + enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)) { struct authsvc *asp; switch (cred_flavor) { case AUTH_NULL: - case AUTH_UNIX: + case AUTH_SYS: case AUTH_SHORT: #ifdef DES_BUILTIN case AUTH_DES: @@ -183,22 +174,26 @@ svc_auth_reg(int cred_flavor, enum auth_stat (*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 67f7401103..3ed9814332 100644 --- a/lib/libc/rpc/svc_auth_des.c +++ b/lib/libc/rpc/svc_auth_des.c @@ -3,7 +3,7 @@ * Copyright (c) 1988 by Sun Microsystems, Inc. * * @(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI - * $FreeBSD: src/lib/libc/rpc/svc_auth_des.c,v 1.3 1999/08/28 00:00:48 peter Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_auth_des.c,v 1.9 2002/03/22 23:18:37 obrien Exp $ * $DragonFly: src/lib/libc/rpc/svc_auth_des.c,v 1.6 2005/11/13 12:27:04 swildner Exp $ */ @@ -50,6 +50,8 @@ * */ +#include "namespace.h" +#include "reentrant.h" #include #include #include @@ -64,6 +66,9 @@ #include #include #include +#include "libc_private.h" + +extern int key_decryptsession_pk(const char *, netobj *, des_block *); #define debug(msg) printf("svcauth_des: %s\n", msg) @@ -187,7 +192,7 @@ _svcauth_des(struct svc_req *rqst, struct rpc_msg *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 3a799c7813..8ca14d41ca 100644 --- a/lib/libc/rpc/svc_auth_unix.c +++ b/lib/libc/rpc/svc_auth_unix.c @@ -28,7 +28,7 @@ * * @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro * @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_auth_unix.c,v 1.8 1999/08/28 00:00:49 peter Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_auth_unix.c,v 1.11 2004/10/16 06:11:35 obrien Exp $ * $DragonFly: src/lib/libc/rpc/svc_auth_unix.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -43,9 +43,13 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include #include #include + #include +#include "un-namespace.h" /* * Unix longhand authenticator @@ -63,8 +67,11 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) int area_gids[NGRPS]; } *area; u_int auth_len; - int str_len, gid_len; - 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; @@ -74,34 +81,34 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *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) { - printf("bad auth_len gid %d str %d auth %d\n", - gid_len, str_len, auth_len); + printf("bad auth_len gid %ld str %ld auth %u\n", + (long)gid_len, (long)str_len, auth_len); stat = AUTH_BADCRED; goto done; } @@ -112,13 +119,13 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *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; diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c new file mode 100644 index 0000000000..07797d8ba0 --- /dev/null +++ b/lib/libc/rpc/svc_dg.c @@ -0,0 +1,573 @@ +/* + * 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 + * + * @(#)svc_dg.c 1.17 94/04/24 SMI + * $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_dg.c,v 1.8 2006/02/27 22:10:59 deischen Exp $ + * $DragonFly$ + */ + +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * svc_dg.c, Server side for connectionless RPC. + * + * Does some caching in the hopes of achieving execute-at-most-once semantics. + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef RPC_CACHE_DEBUG +#include +#include +#endif +#include +#include "un-namespace.h" + +#include "rpc_com.h" +#include "mt_misc.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(SVCXPRT *); +static enum xprt_stat svc_dg_stat(SVCXPRT *); +static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *); +static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *); +static bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *); +static bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *); +static void svc_dg_destroy(SVCXPRT *); +static bool_t svc_dg_control(SVCXPRT *, const u_int, void *); +static int cache_get(SVCXPRT *, struct rpc_msg *, char **, size_t *); +static void cache_set(SVCXPRT *, size_t); +int svc_dg_enablecache(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(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 = 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: + warnx(svc_dg_str, __no_mem_str); + if (xprt) { + if (su) + mem_free(su, sizeof (*su)); + mem_free(xprt, sizeof (SVCXPRT)); + } + return (NULL); +} + +/*ARGSUSED*/ +static enum xprt_stat +svc_dg_stat(SVCXPRT *xprt) +{ + return (XPRT_IDLE); +} + +static bool_t +svc_dg_recv(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; + ssize_t 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 < (ssize_t)(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)) { + _sendto(xprt->xp_fd, reply, replylen, 0, + (struct sockaddr *)(void *)&ss, alen); + return (FALSE); + } + } + return (TRUE); +} + +static bool_t +svc_dg_reply(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) == (ssize_t) slen) { + stat = TRUE; + if (su->su_cache) + cache_set(xprt, slen); + } + } + return (stat); +} + +static bool_t +svc_dg_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) +{ + return (*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr); +} + +static bool_t +svc_dg_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *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(SVCXPRT *xprt) +{ + struct svc_dg_data *su = su_data(xprt); + + xprt_unregister(xprt); + if (xprt->xp_fd != -1) + _close(xprt->xp_fd); + XDR_DESTROY(&(su->su_xdrs)); + mem_free(rpc_buffer(xprt), su->su_iosz); + mem_free(su, sizeof (*su)); + 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); + mem_free(xprt, sizeof (SVCXPRT)); +} + +static bool_t +/*ARGSUSED*/ +svc_dg_control(SVCXPRT *xprt, const u_int rq, void *in) +{ + return (FALSE); +} + +static void +svc_dg_ops(SVCXPRT *xprt) +{ + static struct xp_ops ops; + static struct xp_ops2 ops2; + +/* 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) \ + 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)) + +/* + * 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(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) { + 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(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); + 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(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 0000000000..1151675653 --- /dev/null +++ b/lib/libc/rpc/svc_generic.c @@ -0,0 +1,304 @@ +/* + * 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 + * + * @(#)svc_generic.c 1.19 94/04/24 SMI; 1.21 89/02/28 Copyr 1988 Sun Micro + * $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_generic.c,v 1.7 2006/02/27 22:10:59 deischen Exp $ + * $DragonFly$ + */ + +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +/* + * svc_generic.c, Server side for RPC. + */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + +#include "rpc_com.h" +#include "mt_misc.h" + +extern int __svc_vc_setflag(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(void (*dispatch)(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; + +/* 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 */ + 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(void (*dispatch)(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*/ + 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( + 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 *)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) + _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 c6e02cab69..767061d7ad 100644 --- a/lib/libc/rpc/svc_raw.c +++ b/lib/libc/rpc/svc_raw.c @@ -26,132 +26,212 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * - * @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro - * @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_raw.c,v 1.7 1999/08/28 00:00:49 peter Exp $ + * @(#)svc_raw.c 1.25 89/01/31 Copyr 1984 Sun Micro + * @(#)svc_raw.c 1.16 94/04/24 SMI + * $NetBSD: svc_raw.c,v 1.14 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_raw.c,v 1.15 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/svc_raw.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ /* * svc_raw.c, This a toy for simple testing and timing. * Interface to create an rpc client and server in the same UNIX process. * This lets us similate rpc and get rpc (round trip) overhead, without - * any interference from the kernal. + * any interference from the kernel. * - * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "namespace.h" +#include "reentrant.h" #include +#include +#include #include +#include "un-namespace.h" +#include "mt_misc.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; + +static enum xprt_stat svc_raw_stat(SVCXPRT *); +static bool_t svc_raw_recv(SVCXPRT *, struct rpc_msg *); +static bool_t svc_raw_reply(SVCXPRT *, struct rpc_msg *); +static bool_t svc_raw_getargs(SVCXPRT *, xdrproc_t, void *); +static bool_t svc_raw_freeargs(SVCXPRT *, xdrproc_t, void *); +static void svc_raw_destroy(SVCXPRT *); +static void svc_raw_ops(SVCXPRT *); +static bool_t svc_raw_control(SVCXPRT *, const u_int, void *); + +char *__rpc_rawcombuf = NULL; SVCXPRT * -svcraw_create(void) +svc_raw_create(void) { - struct svcraw_private *srp = svcraw_private; - - if (srp == 0) { - srp = (struct svcraw_private *)calloc(1, sizeof (*srp)); - if (srp == 0) - return (0); + struct svc_raw_private *srp; +/* VARIABLES PROTECTED BY svcraw_lock: svc_raw_private, srp */ + + 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(void) +svc_raw_stat(SVCXPRT *xprt) { - return (XPRT_IDLE); } +/*ARGSUSED*/ static bool_t -svcraw_recv(SVCXPRT *xprt, struct rpc_msg *msg) +svc_raw_recv(SVCXPRT *xprt, struct rpc_msg *msg) { - struct svcraw_private *srp = svcraw_private; + struct svc_raw_private *srp; XDR *xdrs; - if (srp == 0) - return (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_DECODE; XDR_SETPOS(xdrs, 0); - if (! xdr_callmsg(xdrs, msg)) - return (FALSE); + if (! xdr_callmsg(xdrs, msg)) { + return (FALSE); + } return (TRUE); } +/*ARGSUSED*/ static bool_t -svcraw_reply(SVCXPRT *xprt, struct rpc_msg *msg) +svc_raw_reply(SVCXPRT *xprt, struct rpc_msg *msg) { - struct svcraw_private *srp = svcraw_private; + 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); + if (! xdr_replymsg(xdrs, msg)) { + return (FALSE); + } XDR_GETPOS(xdrs); /* called just for overhead */ return (TRUE); } +/*ARGSUSED*/ static bool_t -svcraw_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +svc_raw_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) { - 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(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +svc_raw_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) { - struct svcraw_private *srp = svcraw_private; + 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(SVCXPRT *xprt) +{ +} + +/*ARGSUSED*/ +static bool_t +svc_raw_control(SVCXPRT *xprt, const u_int rq, void *in) +{ + return (FALSE); } static void -svcraw_destroy(void) +svc_raw_ops(SVCXPRT *xprt) { + static struct xp_ops ops; + static struct xp_ops2 ops2; + +/* 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 a4babe9107..8ffc709c19 100644 --- a/lib/libc/rpc/svc_run.c +++ b/lib/libc/rpc/svc_run.c @@ -28,7 +28,8 @@ * * @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro * @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_run.c,v 1.10 1999/08/28 00:00:49 peter Exp $ + * $NetBSD: svc_run.c,v 1.17 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_run.c,v 1.20 2006/02/27 22:10:59 deischen Exp $ * $DragonFly: src/lib/libc/rpc/svc_run.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ */ @@ -37,52 +38,58 @@ * Wait for input, call server program. */ #include "namespace.h" +#include "reentrant.h" +#include +#include #include #include -#include -#include -#include -#include -#include #include +#include #include "un-namespace.h" -extern int __svc_fdsetsize; -extern fd_set *__svc_fdset; +#include +#include "rpc_com.h" +#include "mt_misc.h" void svc_run(void) { - fd_set *fds; + fd_set readfds, cleanfds; + struct timeval timeout; + + timeout.tv_sec = 30; + timeout.tv_usec = 0; 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; + cleanfds = svc_fdset; + rwlock_unlock(&svc_fd_lock); + switch (_select(svc_maxfd+1, &readfds, NULL, NULL, &timeout)) { 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); + __svc_clean_idle(&cleanfds, 30, FALSE); 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(void) +{ + 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 d35de7dbfa..f99ec25b13 100644 --- a/lib/libc/rpc/svc_simple.c +++ b/lib/libc/rpc/svc_simple.c @@ -28,118 +28,283 @@ * * @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro * @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_simple.c,v 1.9 1999/08/28 00:00:50 peter Exp $ + * $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_simple.c,v 1.16 2006/09/09 22:32:07 mbr Exp $ * $DragonFly: src/lib/libc/rpc/svc_simple.c,v 1.3 2005/11/13 12:27:04 swildner Exp $ */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ /* * 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 "namespace.h" +#include "reentrant.h" +#include +#include +#include #include #include #include -#include -#include -#include -#include +#include +#include "un-namespace.h" + +#include "rpc_com.h" +#include "mt_misc.h" + +static void universal(struct svc_req *, SVCXPRT *); static struct proglst { - char *(*p_progname)(); - int p_prognum; - int p_procnum; + char *(*p_progname)(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(int prognum, int versnum, int procnum, char *(*progname)(), - xdrproc_t inproc, xdrproc_t outproc) +rpc_reg(rpcprog_t prognum, /* program number */ + rpcvers_t versnum, /* version number */ + rpcproc_t procnum, /* procedure number */ + char *(*progname)(char *), /* Server routine */ + xdrproc_t inproc, xdrproc_t outproc, /* in/out XDR procedures */ + char *nettype) /* nettype */ { + struct netconfig *nconf; + int done = FALSE; + void *handle; + if (procnum == NULLPROC) { - 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) { - fprintf(stderr, "couldn't create an rpc server\n"); - return (-1); - } - } - pmap_unset((u_long)prognum, (u_long)versnum); - if (!svc_register(transp, (u_long)prognum, (u_long)versnum, - universal, IPPROTO_UDP)) { - 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) { - 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; + recvsz = 0; + xdrbuf = netid = 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); + if (xdrbuf != NULL) + free(xdrbuf); + if (netid != NULL) + free(netid); + 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 */ + 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(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; /* * enforce "procnum 0 is echo" convention */ if (rqstp->rq_proc == NULLPROC) { - if (svc_sendreply(transp, xdr_void, NULL) == FALSE) { - 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 ! */ + 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)) { - 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 */ svc_freeargs(transp, pl->p_inproc, xdrbuf); + mutex_unlock(&proglst_lock); return; } - 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 00ef1d50e3..0000000000 --- a/lib/libc/rpc/svc_tcp.c +++ /dev/null @@ -1,458 +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 - * - * @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro - * @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_tcp.c,v 1.18.2.3 2001/09/05 22:29:23 dec Exp $ - * $DragonFly: src/lib/libc/rpc/svc_tcp.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#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(int sock, u_int sendsize, u_int recvsize) -{ - bool_t madesock = FALSE; - SVCXPRT *xprt; - 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 - tcp 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) - _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; - _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) - _close(sock); - return ((SVCXPRT *)NULL); - } - r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r)); - if (r == NULL) { - 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) { - 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(int fd, u_int sendsize, u_int recvsize) -{ - - return (makefd_xprt(fd, sendsize, recvsize)); -} - -static SVCXPRT * -makefd_xprt(int fd, u_int sendsize, u_int recvsize) -{ - SVCXPRT *xprt; - struct tcp_conn *cd; - - xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); - if (xprt == (SVCXPRT *)NULL) { - 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) { - 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(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(void) -{ - - return (XPRT_IDLE); -} - -static void -svctcp_destroy(SVCXPRT *xprt) -{ - struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1; - - xprt_unregister(xprt); - _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(SVCXPRT *xprt, caddr_t buf, int len) -{ - 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: - memset(fds, 0, bytes); - 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(SVCXPRT *xprt, caddr_t buf, int len) -{ - 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(SVCXPRT *xprt) -{ - 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(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct tcp_conn *cd = - (struct tcp_conn *)(xprt->xp_p1); - XDR *xdrs = &(cd->xdrs); - - xdrs->x_op = XDR_DECODE; - 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(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(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) -{ - 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(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct tcp_conn *cd = - (struct tcp_conn *)(xprt->xp_p1); - XDR *xdrs = &(cd->xdrs); - bool_t stat; - - xdrs->x_op = XDR_ENCODE; - msg->rm_xid = cd->x_id; - stat = xdr_replymsg(xdrs, msg); - 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 e9461122f6..0000000000 --- a/lib/libc/rpc/svc_udp.c +++ /dev/null @@ -1,459 +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 - * - * @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro - * @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_udp.c,v 1.13 2000/01/27 23:06:41 jasone Exp $ - * $DragonFly: src/lib/libc/rpc/svc_udp.c,v 1.6 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#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 (SVCXPRT *, u_long); -static int cache_get (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(int sock, u_int sendsz, u_int recvsz) -{ - bool_t madesock = FALSE; - SVCXPRT *xprt; - 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; - _bind(sock, (struct sockaddr *)&addr, len); - } - if (_getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { - perror("svcudp_create - cannot getsockname"); - if (madesock) - _close(sock); - return ((SVCXPRT *)NULL); - } - xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); - if (xprt == NULL) { - fprintf(stderr, "svcudp_create: out of memory\n"); - return (NULL); - } - su = (struct svcudp_data *)mem_alloc(sizeof(*su)); - if (su == NULL) { - 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) { - 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(int sock) -{ - - return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE)); -} - -static enum xprt_stat -svcudp_stat(SVCXPRT *xprt) -{ - - return (XPRT_IDLE); -} - -static bool_t -svcudp_recv(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct svcudp_data *su = su_data(xprt); - XDR *xdrs = &(su->su_xdrs); - 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)) { - _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(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct svcudp_data *su = su_data(xprt); - XDR *xdrs = &(su->su_xdrs); - int slen; - 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(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(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 -svcudp_destroy(SVCXPRT *xprt) -{ - struct svcudp_data *su = su_data(xprt); - - xprt_unregister(xprt); - _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) \ - 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(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(SVCXPRT *xprt, u_long replylen) -{ - cache_ptr victim; - cache_ptr *vicp; - 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(SVCXPRT *xprt, struct rpc_msg *msg, char **replyp, u_long *replylenp) -{ - u_int loc; - cache_ptr ent; - struct svcudp_data *su = su_data(xprt); - 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 a48ec399d6..0000000000 --- a/lib/libc/rpc/svc_unix.c +++ /dev/null @@ -1,499 +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 - * - * @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro - * @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/rpc/svc_unix.c,v 1.7.2.2 2001/09/05 22:29:23 dec Exp $ - * $DragonFly: src/lib/libc/rpc/svc_unix.c,v 1.5 2005/11/13 12:27:04 swildner Exp $ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#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(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(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(int sock, u_int sendsize, u_int recvsize, char *path) -{ - bool_t madesock = FALSE; - SVCXPRT *xprt; - 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) - _close(sock); - return ((SVCXPRT *)NULL); - } - r = (struct unix_rendezvous *)mem_alloc(sizeof(*r)); - if (r == NULL) { - 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) { - 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(int fd, u_int sendsize, u_int recvsize) -{ - - return (makefd_xprt(fd, sendsize, recvsize)); -} - -static SVCXPRT * -makefd_xprt(int fd, u_int sendsize, u_int recvsize) -{ - SVCXPRT *xprt; - struct unix_conn *cd; - - xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); - if (xprt == (SVCXPRT *)NULL) { - 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) { - 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(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(void) -{ - - return (XPRT_IDLE); -} - -static void -svcunix_destroy(SVCXPRT *xprt) -{ - struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1; - - xprt_unregister(xprt); - _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(SVCXPRT *xprt, caddr_t buf, int len) -{ - 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: - memset(fds, 0, bytes); - 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(SVCXPRT *xprt, caddr_t buf, int len) -{ - 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(SVCXPRT *xprt) -{ - 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(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct unix_conn *cd = - (struct unix_conn *)(xprt->xp_p1); - XDR *xdrs = &(cd->xdrs); - - xdrs->x_op = XDR_DECODE; - 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(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(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) -{ - 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(SVCXPRT *xprt, struct rpc_msg *msg) -{ - struct unix_conn *cd = - (struct unix_conn *)(xprt->xp_p1); - XDR *xdrs = &(cd->xdrs); - bool_t stat; - - xdrs->x_op = XDR_ENCODE; - msg->rm_xid = cd->x_id; - stat = xdr_replymsg(xdrs, msg); - 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 0000000000..4673ec9536 --- /dev/null +++ b/lib/libc/rpc/svc_vc.c @@ -0,0 +1,750 @@ +/* + * 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 + * + * @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro + * @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC + * $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ + * $FreeBSD: src/lib/libc/rpc/svc_vc.c,v 1.27 2008/03/30 09:36:17 dfr Exp $ + * $DragonFly$ + */ + +/* + * 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 "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rpc_com.h" +#include "mt_misc.h" +#include "un-namespace.h" + +static SVCXPRT *makefd_xprt(int, u_int, u_int); +static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat(SVCXPRT *); +static void svc_vc_destroy(SVCXPRT *); +static void __svc_vc_dodestroy (SVCXPRT *); +static int read_vc(void *, void *, int); +static int write_vc(void *, void *, int); +static enum xprt_stat svc_vc_stat(SVCXPRT *); +static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); +static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *); +static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *); +static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); +static void svc_vc_rendezvous_ops(SVCXPRT *); +static void svc_vc_ops(SVCXPRT *); +static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); +static bool_t svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, + void *in); + +struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ + u_int sendsize; + u_int recvsize; + int maxrec; +}; + +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]; + u_int sendsize; + u_int recvsize; + int maxrec; + bool_t nonblock; + struct timeval last_recv_time; +}; + +/* + * 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(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; + + if (!__rpc_fd2sockinfo(fd, &si)) + return NULL; + + r = mem_alloc(sizeof(*r)); + if (r == NULL) { + warnx("svc_vc_create: out of memory"); + goto cleanup_svc_vc_create; + } + 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); + r->maxrec = __svc_maxrec; + 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 = 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 (xprt) + mem_free(xprt, sizeof(*xprt)); + 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(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 || ss.ss_family == AF_LOCAL) { + 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(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, + xprt, read_vc, write_vc); + xprt->xp_p1 = 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(SVCXPRT *xprt, struct rpc_msg *msg) +{ + int sock, flags; + struct cf_rendezvous *r; + struct cf_conn *cd; + struct sockaddr_storage addr; + socklen_t len; + struct __rpc_sockinfo si; + SVCXPRT *newxprt; + fd_set cleanfds; + + 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; + /* + * Clean out the most idle file descriptor when we're + * running out. + */ + if (errno == EMFILE || errno == ENFILE) { + cleanfds = svc_fdset; + __svc_clean_idle(&cleanfds, 0, FALSE); + goto again; + } + return (FALSE); + } + /* + * make a new transporter (re-uses xprt) + */ + newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); + newxprt->xp_rtaddr.buf = mem_alloc(len); + if (newxprt->xp_rtaddr.buf == NULL) + return (FALSE); + memcpy(newxprt->xp_rtaddr.buf, &addr, len); + newxprt->xp_rtaddr.len = len; +#ifdef PORTMAP + if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) { + newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf; + newxprt->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)); + } + + cd = (struct cf_conn *)newxprt->xp_p1; + + cd->recvsize = r->recvsize; + cd->sendsize = r->sendsize; + cd->maxrec = r->maxrec; + + if (cd->maxrec != 0) { + flags = _fcntl(sock, F_GETFL, 0); + if (flags == -1) + return (FALSE); + if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) + return (FALSE); + if (cd->recvsize > cd->maxrec) + cd->recvsize = cd->maxrec; + cd->nonblock = TRUE; + __xdrrec_setnonblock(&cd->xdrs, cd->maxrec); + } else + cd->nonblock = FALSE; + + gettimeofday(&cd->last_recv_time, NULL); + + return (FALSE); /* there is never an rpc msg to be processed */ +} + +/*ARGSUSED*/ +static enum xprt_stat +rendezvous_stat(SVCXPRT *xprt) +{ + + return (XPRT_IDLE); +} + +static void +svc_vc_destroy(SVCXPRT *xprt) +{ + assert(xprt != NULL); + + xprt_unregister(xprt); + __svc_vc_dodestroy(xprt); +} + +static void +__svc_vc_dodestroy(SVCXPRT *xprt) +{ + struct cf_conn *cd; + struct cf_rendezvous *r; + + cd = (struct cf_conn *)xprt->xp_p1; + + if (xprt->xp_fd != RPC_ANYFD) + _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(SVCXPRT *xprt, const u_int rq, void *in) +{ + return (FALSE); +} + +static bool_t +svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in) +{ + struct cf_rendezvous *cfp; + + cfp = (struct cf_rendezvous *)xprt->xp_p1; + if (cfp == NULL) + return (FALSE); + switch (rq) { + case SVCGET_CONNMAXREC: + *(int *)in = cfp->maxrec; + break; + case SVCSET_CONNMAXREC: + cfp->maxrec = *(int *)in; + break; + default: + return (FALSE); + } + return (TRUE); +} + +/* + * 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(void *xprtp, void *buf, int len) +{ + SVCXPRT *xprt; + int sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + struct cf_conn *cfp; + + xprt = (SVCXPRT *)xprtp; + assert(xprt != NULL); + + sock = xprt->xp_fd; + + cfp = (struct cf_conn *)xprt->xp_p1; + + if (cfp->nonblock) { + len = _read(sock, buf, (size_t)len); + if (len < 0) { + if (errno == EAGAIN) + len = 0; + else + goto fatal_err; + } + if (len != 0) + gettimeofday(&cfp->last_recv_time, NULL); + return len; + } + + 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); + + if ((len = _read(sock, buf, (size_t)len)) > 0) { + gettimeofday(&cfp->last_recv_time, NULL); + 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(void *xprtp, void *buf, int len) +{ + SVCXPRT *xprt; + int i, cnt; + struct cf_conn *cd; + struct timeval tv0, tv1; + + xprt = (SVCXPRT *)xprtp; + assert(xprt != NULL); + + cd = (struct cf_conn *)xprt->xp_p1; + + if (cd->nonblock) + gettimeofday(&tv0, NULL); + + for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) { + i = _write(xprt->xp_fd, buf, (size_t)cnt); + if (i < 0) { + if (errno != EAGAIN || !cd->nonblock) { + cd->strm_stat = XPRT_DIED; + return (-1); + } + if (cd->nonblock && i != cnt) { + /* + * For non-blocking connections, do not + * take more than 2 seconds writing the + * data out. + * + * XXX 2 is an arbitrary amount. + */ + gettimeofday(&tv1, NULL); + if (tv1.tv_sec - tv0.tv_sec >= 2) { + cd->strm_stat = XPRT_DIED; + return (-1); + } + } + } + } + + return (len); +} + +static enum xprt_stat +svc_vc_stat(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(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); + + if (cd->nonblock) { + if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE)) + return FALSE; + } else { + xdrrec_skiprecord(xdrs); + } + + xdrs->x_op = XDR_DECODE; + 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(SVCXPRT *xprt, xdrproc_t xdr_args, void *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(SVCXPRT *xprt, xdrproc_t xdr_args, void *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(SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct cf_conn *cd; + XDR *xdrs; + bool_t rstat; + + 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; + rstat = xdr_replymsg(xdrs, msg); + xdrrec_endofrecord(xdrs, TRUE); + return (rstat); +} + +static void +svc_vc_ops(SVCXPRT *xprt) +{ + static struct xp_ops ops; + static struct xp_ops2 ops2; + +/* 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(SVCXPRT *xprt) +{ + static struct xp_ops ops; + static struct xp_ops2 ops2; + + mutex_lock(&ops_lock); + if (ops.xp_recv == NULL) { + ops.xp_recv = rendezvous_request; + ops.xp_stat = rendezvous_stat; + ops.xp_getargs = + (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort; + ops.xp_reply = + (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort; + ops.xp_freeargs = + (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort, + ops.xp_destroy = svc_vc_destroy; + ops2.xp_control = svc_vc_rendezvous_control; + } + xprt->xp_ops = &ops; + xprt->xp_ops2 = &ops2; + mutex_unlock(&ops_lock); +} + +/* + * Get the effective UID of the sending process. Used by rpcbind, keyserv + * and rpc.yppasswdd on AF_LOCAL. + */ +int +__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) +{ + int sock, ret; + gid_t egid; + uid_t euid; + struct sockaddr *sa; + + sock = transp->xp_fd; + sa = (struct sockaddr *)transp->xp_rtaddr.buf; + if (sa->sa_family == AF_LOCAL) { + ret = getpeereid(sock, &euid, &egid); + if (ret == 0) + *uid = euid; + return (ret); + } else + return (-1); +} + +/* + * Destroy xprts that have not have had any activity in 'timeout' seconds. + * If 'cleanblock' is true, blocking connections (the default) are also + * cleaned. If timeout is 0, the least active connection is picked. + */ +bool_t +__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) +{ + int i, ncleaned; + SVCXPRT *xprt, *least_active; + struct timeval tv, tdiff, tmax; + struct cf_conn *cd; + + gettimeofday(&tv, NULL); + tmax.tv_sec = tmax.tv_usec = 0; + least_active = NULL; + rwlock_wrlock(&svc_fd_lock); + for (i = ncleaned = 0; i <= svc_maxfd; i++) { + if (FD_ISSET(i, fds)) { + xprt = __svc_xports[i]; + if (xprt == NULL || xprt->xp_ops == NULL || + xprt->xp_ops->xp_recv != svc_vc_recv) + continue; + cd = (struct cf_conn *)xprt->xp_p1; + if (!cleanblock && !cd->nonblock) + continue; + if (timeout == 0) { + timersub(&tv, &cd->last_recv_time, &tdiff); + if (timercmp(&tdiff, &tmax, >)) { + tmax = tdiff; + least_active = xprt; + } + continue; + } + if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { + __xprt_unregister_unlocked(xprt); + __svc_vc_dodestroy(xprt); + ncleaned++; + } + } + } + if (timeout == 0 && least_active != NULL) { + __xprt_unregister_unlocked(least_active); + __svc_vc_dodestroy(least_active); + ncleaned++; + } + rwlock_unlock(&svc_fd_lock); + return ncleaned > 0 ? TRUE : FALSE; +} diff --git a/lib/libc/xdr/Makefile.inc b/lib/libc/xdr/Makefile.inc index 57fa82f475..d0610a15a5 100644 --- a/lib/libc/xdr/Makefile.inc +++ b/lib/libc/xdr/Makefile.inc @@ -1,15 +1,22 @@ # @(#)Makefile 5.11 (Berkeley) 9/6/90 -# $FreeBSD: src/lib/libc/xdr/Makefile.inc,v 1.10.2.1 2001/04/25 10:04:19 ru Exp $ +# $FreeBSD: src/lib/libc/xdr/Makefile.inc,v 1.15 2006/03/13 01:15:01 deischen Exp $ # $DragonFly: src/lib/libc/xdr/Makefile.inc,v 1.2 2003/06/17 04:26:47 dillon Exp $ .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" MAN+= 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 \ diff --git a/lib/libc/xdr/xdr.3 b/lib/libc/xdr/xdr.3 index 35ce0057c7..8c6a05664a 100644 --- a/lib/libc/xdr/xdr.3 +++ b/lib/libc/xdr/xdr.3 @@ -1,12 +1,49 @@ .\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI -.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.8.2.4 2001/12/14 18:34:06 ru Exp $ +.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.17 2005/11/24 07:12:01 ru Exp $ .\" $DragonFly: src/lib/libc/xdr/xdr.3,v 1.3 2007/11/23 23:16:36 swildner Exp $ .\" .Dd February 16, 1988 .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 @@ -42,15 +79,16 @@ A filter primitive that translates between variable-length arrays and their corresponding external representations. The -parameter .Fa arrp +argument is the address of the pointer to the array, while .Fa sizep is the address of the element count of the array; this element count cannot exceed .Fa maxsize . -The parameter +The .Fa elsize +argument is the .Ic sizeof each of the array's elements, and @@ -85,8 +123,9 @@ This routine returns one if it succeeds, zero otherwise. .Pp A filter primitive that translates between counted byte strings and their external representations. -The parameter +The .Fa sp +argument is the address of the string pointer. The length of the string is located at address @@ -173,7 +212,7 @@ This routine returns one if it succeeds, zero otherwise. .Ft void .Xc .It Xo -.Fn xdr_free "xdrproc_t proc" "char *objp" +.Fn xdr_free "xdrproc_t proc" "void *objp" .Xc .Pp Generic freeing routine. @@ -213,6 +252,17 @@ although the stream instances need not guarantee this. .Pp .It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_hyper "XDR *xdrs" "quad_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 @@ -263,6 +313,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" "quad_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 @@ -281,6 +342,7 @@ whose length is no more than bytes long. The .Fa op +argument determines the direction of the .Tn XDR stream @@ -300,8 +362,9 @@ or A filter primitive that translates between fixed size opaque data and its external representation. -The parameter +The .Fa cp +argument is the address of the opaque object, and .Fa cnt is its size in bytes. @@ -335,7 +398,7 @@ linked lists. .Fa "XDR *xdrs" .Fa "u_int sendsize" .Fa "u_int recvsize" -.Fa "char *handle" +.Fa "void *handle" .Fa "int \*(lp*readit\*(rp\*(lp\*(rp" .Fa "int \*(lp*writeit\*(rp\*(lp\*(rp" .Fc @@ -367,7 +430,7 @@ and .Xr write 2 , except that .Fa handle -is passed to the former routines as the first parameter. +is passed to the former routines as the first argument. Note: the .Tn XDR stream's @@ -436,8 +499,9 @@ This routine returns one if it succeeds, zero otherwise. .Xc .Pp A primitive that provides pointer chasing within structures. -The parameter +The .Fa pp +argument is the address of the pointer; .Fa size is the @@ -471,8 +535,9 @@ the .Tn XDR stream .Fa xdrs . -The parameter +The .Fa pos +argument is a position value obtained from .Fn xdr_getpos . This routine returns one if the @@ -517,8 +582,9 @@ stream data is written to, or read from, the Standard .Tn I/O stream .Fa file . -The parameter +The .Fa op +argument determines the direction of the .Tn XDR stream (either @@ -569,6 +635,19 @@ This routine returns one if it succeeds, zero otherwise. .Ft int .Xc .It Xo +.Fn xdr_u_hyper "XDR *xdrs" "u_quad_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 @@ -593,6 +672,19 @@ This routine returns one if it succeeds, zero otherwise. .Ft int .Xc .It Xo +.Fn xdr_u_longlong_t "XDR *xdrs" "u_quad_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 @@ -607,10 +699,10 @@ This routine returns one if it succeeds, zero otherwise. .It Xo .Fo xdr_union .Fa "XDR *xdrs" -.Fa "int *dscmp" +.Fa "enum_t *dscmp" .Fa "char *unp" -.Fa "struct xdr_discrim *choices" -.Fa "bool_t \*(lp*defaultarm\*(rp\*(lp\*(rp" +.Fa "const struct xdr_discrim *choices" +.Fa "xdrproc_t defaultarm" .Fc .Xc .Pp @@ -625,8 +717,9 @@ This discriminant is always an Next the union located at .Fa unp is translated. -The parameter +The .Fa choices +argument is a pointer to an array of .Vt xdr_discrim structures. @@ -666,13 +759,14 @@ A filter primitive that translates between fixed-length arrays and their corresponding external representations. The -parameter .Fa arrp +argument is the address of the pointer to the array, while .Fa size is the element count of the array. -The parameter +The .Fa elsize +argument is the .Ic sizeof each of the array's elements, and @@ -694,7 +788,7 @@ This routine returns one if it succeeds, zero otherwise. This routine always returns one. It may be passed to .Tn RPC -routines that require a function parameter, +routines that require a function argument, where nothing is to be done. .Pp .It Xo @@ -709,12 +803,14 @@ A primitive that calls where .Dv MAXUN.UNSIGNED is the maximum value of an unsigned integer. +The .Fn xdr_wrapstring +function is handy because the .Tn RPC package passes a maximum of two .Tn XDR -routines as parameters, and +routines as arguments, and .Fn xdr_string , one of the most frequently used primitives, requires three. Returns one if it succeeds, zero otherwise. diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c index 391fc52141..859da81840 100644 --- a/lib/libc/xdr/xdr.c +++ b/lib/libc/xdr/xdr.c @@ -28,7 +28,8 @@ * * @(#)xdr.c 1.35 87/08/12 * @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9.2.1 2000/05/06 21:16:04 dec Exp $ + * $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr.c,v 1.14 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr.c,v 1.4 2005/12/05 00:47:57 swildner Exp $ */ @@ -42,12 +43,18 @@ * xdr. */ +#include "namespace.h" +#include #include #include #include #include #include +#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" @@ -59,14 +66,14 @@ /* * 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 * Not a filter, but a convenient utility nonetheless */ void -xdr_free(xdrproc_t proc, char *objp) +xdr_free(xdrproc_t proc, void *objp) { XDR x; @@ -80,6 +87,7 @@ xdr_free(xdrproc_t proc, char *objp) bool_t xdr_void(void) { + return (TRUE); } @@ -108,6 +116,7 @@ xdr_int(XDR *xdrs, int *ip) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -135,6 +144,7 @@ xdr_u_int(XDR *xdrs, u_int *up) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -154,7 +164,7 @@ xdr_long(XDR *xdrs, long *lp) case XDR_FREE: return (TRUE); } - + /* NOTREACHED */ return (FALSE); } @@ -173,6 +183,7 @@ xdr_u_long(XDR *xdrs, u_long *ulp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -202,6 +213,7 @@ xdr_int32_t(XDR *xdrs, int32_t *int32_p) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -230,67 +242,7 @@ xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p) case XDR_FREE: return (TRUE); } - return (FALSE); -} - -/* - * XDR 64-bit integers - */ -bool_t -xdr_int64_t(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(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); } @@ -319,6 +271,7 @@ xdr_short(XDR *xdrs, short *sp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -346,6 +299,7 @@ xdr_u_short(XDR *xdrs, u_short *usp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -374,6 +328,7 @@ xdr_int16_t(XDR *xdrs, int16_t *int16_p) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -401,6 +356,7 @@ xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -461,6 +417,7 @@ xdr_bool(XDR *xdrs, bool_t *bp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -470,26 +427,20 @@ xdr_bool(XDR *xdrs, bool_t *bp) bool_t xdr_enum(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 - (xdr_short(xdrs, (short *)ep)); - (xdr_int(xdrs, (int *)ep)); - return (xdr_long(xdrs, (long *)ep)); -#endif } /* @@ -522,7 +473,7 @@ xdr_opaque(XDR *xdrs, caddr_t cp, u_int 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) { @@ -573,13 +524,13 @@ xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) return (TRUE); } if (sp == NULL) { - *cpp = sp = (char *)mem_alloc(nodesize); + *cpp = sp = mem_alloc(nodesize); } if (sp == NULL) { - 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)); @@ -591,6 +542,7 @@ xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) } return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -621,8 +573,8 @@ xdr_netobj(XDR *xdrs, struct netobj *np) * dfault: default xdr routine */ bool_t -xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, struct xdr_discrim *choices, - xdrproc_t dfault) +xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, + const struct xdr_discrim *choices, xdrproc_t dfault) { enum_t dscm; @@ -640,14 +592,14 @@ xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, struct xdr_discrim *choices, */ 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)); } @@ -680,7 +632,7 @@ xdr_string(XDR *xdrs, char **cpp, u_int maxsize) if (sp == NULL) { return(TRUE); /* already free */ } - /* fall through... */ + /* FALLTHROUGH */ case XDR_ENCODE: size = strlen(sp); break; @@ -705,13 +657,13 @@ xdr_string(XDR *xdrs, char **cpp, u_int maxsize) return (TRUE); } if (sp == NULL) - *cpp = sp = (char *)mem_alloc(nodesize); + *cpp = sp = mem_alloc(nodesize); if (sp == NULL) { - 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)); @@ -721,6 +673,7 @@ xdr_string(XDR *xdrs, char **cpp, u_int maxsize) *cpp = NULL; return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -733,3 +686,132 @@ xdr_wrapstring(XDR *xdrs, char **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(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(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(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(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(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(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 ed6225ae4a..4479056faf 100644 --- a/lib/libc/xdr/xdr_array.c +++ b/lib/libc/xdr/xdr_array.c @@ -28,7 +28,8 @@ * * @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro * @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_array.c,v 1.8.2.3 2002/08/01 12:23:20 nectar Exp $ + * $NetBSD: xdr_array.c,v 1.12 2000/01/22 22:19:18 mycroft Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_array.c,v 1.15 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr_array.c,v 1.4 2005/12/05 00:47:57 swildner Exp $ */ @@ -41,14 +42,16 @@ * arrays. See xdr.h for more info on the interface to xdr. */ +#include "namespace.h" +#include #include #include #include #include + #include #include - -#define LASTUNSIGNED ((u_int) 0-1) +#include "un-namespace.h" /* * XDR an array of arbitrary elements @@ -96,8 +99,7 @@ xdr_array(XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, return (TRUE); *addrp = target = mem_alloc(nodesize); if (target == NULL) { - fprintf(stderr, - "xdr_array: out of memory\n"); + warnx("xdr_array: out of memory"); return (FALSE); } memset(target, 0, nodesize); @@ -105,6 +107,7 @@ xdr_array(XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, case XDR_FREE: return (TRUE); + case XDR_ENCODE: break; } @@ -113,7 +116,7 @@ xdr_array(XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, * 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; } @@ -146,11 +149,10 @@ xdr_vector(XDR *xdrs, char *basep, u_int nelem, u_int elemsize, 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); } - diff --git a/lib/libc/xdr/xdr_float.c b/lib/libc/xdr/xdr_float.c index f6c6e609cc..7c52dc4394 100644 --- a/lib/libc/xdr/xdr_float.c +++ b/lib/libc/xdr/xdr_float.c @@ -28,12 +28,13 @@ * * @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro * @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_float.c,v 1.7 1999/08/28 00:02:55 peter Exp $ + * $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_float.c,v 1.14 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr_float.c,v 1.6 2006/07/27 00:43:17 corecode Exp $ */ /* - * xdr_float.c, Generic XDR routines impelmentation. + * xdr_float.c, Generic XDR routines implementation. * * Copyright (C) 1984, Sun Microsystems, Inc. * @@ -42,11 +43,15 @@ * xdr. */ -#include +#include "namespace.h" #include #include + +#include + #include #include +#include "un-namespace.h" /* * NB: Not portable. @@ -54,13 +59,14 @@ */ #if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ - defined(__mips__) || defined(__ns32k__) || defined(__arm32__) || \ - defined(__ppc__) || defined(__amd64__) + defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ + defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \ + defined(__arm26__) || defined(__sparc64__) || defined(__amd64__) #include #define IEEEFP #endif -#ifdef vax +#if defined(__vax__) /* What IEEE single precision floating point looks like on a Vax */ struct ieee_single { @@ -94,10 +100,7 @@ static struct sgl_limits { bool_t xdr_float(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; @@ -107,8 +110,7 @@ xdr_float(XDR *xdrs, float *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; @@ -125,17 +127,15 @@ xdr_float(XDR *xdrs, float *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); @@ -157,10 +157,11 @@ xdr_float(XDR *xdrs, float *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; @@ -202,9 +203,8 @@ xdr_double(XDR *xdrs, double *dp) #ifdef IEEEFP int32_t *i32p; bool_t rv; - long tmpl; #else - long *lp; + int32_t *lp; struct ieee_double id; struct vax_double vd; struct dbl_limits *lim; @@ -215,21 +215,17 @@ xdr_double(XDR *xdrs, double *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 @@ -253,32 +249,28 @@ xdr_double(XDR *xdrs, double *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); @@ -305,5 +297,6 @@ xdr_double(XDR *xdrs, double *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 b9f3a6b789..39033b9f80 100644 --- a/lib/libc/xdr/xdr_mem.c +++ b/lib/libc/xdr/xdr_mem.c @@ -28,7 +28,8 @@ * * @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro * @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8.2.1 2003/03/20 12:59:55 jedgar Exp $ + * $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.13 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr_mem.c,v 1.4 2005/12/05 00:47:57 swildner Exp $ */ @@ -43,24 +44,31 @@ * */ +#include "namespace.h" +#include + +#include + #include + #include #include -#include +#include "un-namespace.h" +static void xdrmem_destroy(XDR *); static bool_t xdrmem_getlong_aligned(XDR *, long *); -static bool_t xdrmem_putlong_aligned(XDR *, long *); +static bool_t xdrmem_putlong_aligned(XDR *, const long *); static bool_t xdrmem_getlong_unaligned(XDR *, long *); -static bool_t xdrmem_putlong_unaligned(XDR *, long *); -static bool_t xdrmem_getbytes(XDR *, caddr_t, u_int); -static bool_t xdrmem_putbytes(XDR *, caddr_t, u_int); -static u_int xdrmem_getpos(XDR *); /* XXX w/64-bit pointers, u_int not enough! */ +static bool_t xdrmem_putlong_unaligned(XDR *, const long *); +static bool_t xdrmem_getbytes(XDR *, char *, u_int); +static bool_t xdrmem_putbytes(XDR *, const char *, u_int); +/* XXX: w/64-bit pointers, u_int not enough! */ +static u_int xdrmem_getpos(XDR *); static bool_t xdrmem_setpos(XDR *, u_int); -static int32_t *xdrmem_inline_aligned(XDR *, int); -static int32_t *xdrmem_inline_unaligned(XDR *, int); -static void xdrmem_destroy(void); +static int32_t *xdrmem_inline_aligned(XDR *, u_int); +static int32_t *xdrmem_inline_unaligned(XDR *, u_int); -static struct xdr_ops xdrmem_ops_aligned = { +static const struct xdr_ops xdrmem_ops_aligned = { xdrmem_getlong_aligned, xdrmem_putlong_aligned, xdrmem_getbytes, @@ -71,7 +79,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, @@ -87,19 +95,21 @@ static struct xdr_ops xdrmem_ops_unaligned = { * memory buffer. */ void -xdrmem_create(XDR *xdrs, caddr_t addr, u_int size, enum xdr_op op) +xdrmem_create(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(void) +xdrmem_destroy(XDR *xdrs) { + } static bool_t @@ -109,72 +119,72 @@ xdrmem_getlong_aligned(XDR *xdrs, long *lp) if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); - *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(XDR *xdrs, long *lp) +xdrmem_putlong_aligned(XDR *xdrs, const long *lp) { if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); - *(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(XDR *xdrs, long *lp) { - int32_t l; + u_int32_t l; if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); - 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(XDR *xdrs, long *lp) +xdrmem_putlong_unaligned(XDR *xdrs, const long *lp) { - int32_t l; + u_int32_t l; if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); - 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(XDR *xdrs, caddr_t addr, u_int len) +xdrmem_getbytes(XDR *xdrs, char *addr, u_int len) { if (xdrs->x_handy < len) return (FALSE); xdrs->x_handy -= len; - 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(XDR *xdrs, caddr_t addr, u_int len) +xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len) { if (xdrs->x_handy < len) return (FALSE); xdrs->x_handy -= len; - 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); } @@ -183,14 +193,14 @@ xdrmem_getpos(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(XDR *xdrs, u_int pos) { - caddr_t newaddr = xdrs->x_base + pos; - 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 (newaddr > lastaddr) return (FALSE); @@ -200,20 +210,22 @@ xdrmem_setpos(XDR *xdrs, u_int pos) } static int32_t * -xdrmem_inline_aligned(XDR *xdrs, int len) +xdrmem_inline_aligned(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(XDR *xdrs __unused, int len __unused) +xdrmem_inline_unaligned(XDR *xdrs __unused, u_int len __unused) { + return (0); } diff --git a/lib/libc/xdr/xdr_rec.c b/lib/libc/xdr/xdr_rec.c index 610ad85631..3b7df10832 100644 --- a/lib/libc/xdr/xdr_rec.c +++ b/lib/libc/xdr/xdr_rec.c @@ -28,7 +28,8 @@ * * @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro * @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_rec.c,v 1.12 2000/01/19 06:12:32 wpaul Exp $ + * $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_rec.c,v 1.22 2008/03/30 09:35:04 dfr Exp $ * $DragonFly: src/lib/libc/xdr/xdr_rec.c,v 1.5 2005/12/05 00:47:57 swildner Exp $ */ @@ -49,16 +50,49 @@ * The other 31 bits encode the byte length of the fragment. */ +#include "namespace.h" +#include + +#include + +#include +#include #include #include #include + #include #include -#include +#include +#include +#include +#include "un-namespace.h" +#include "rpc_com.h" + +static bool_t xdrrec_getlong(XDR *, long *); +static bool_t xdrrec_putlong(XDR *, const long *); +static bool_t xdrrec_getbytes(XDR *, char *, u_int); + +static bool_t xdrrec_putbytes(XDR *, const char *, u_int); +static u_int xdrrec_getpos(XDR *); +static bool_t xdrrec_setpos(XDR *, u_int); +static int32_t *xdrrec_inline(XDR *, u_int); +static void xdrrec_destroy(XDR *); + +static const struct xdr_ops xdrrec_ops = { + xdrrec_getlong, + xdrrec_putlong, + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy +}; /* * A record is composed of one or more record fragments. - * A record fragment is a two-byte header followed by zero to + * A record fragment is a four-byte header followed by zero to * 2**32-1 bytes. The header is treated as a long unsigned and is * encode/decoded to the network via htonl/ntohl. The low order 31 bits * are a byte count of the fragment. The highest order bit is a boolean: @@ -72,56 +106,46 @@ #define LAST_FRAG ((u_int32_t)(1 << 31)) typedef struct rec_strm { - caddr_t tcp_handle; - caddr_t the_buffer; + char *tcp_handle; /* - * out-goung bits + * out-going bits */ - int (*writeit) (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 */ + int (*writeit)(void *, void *, 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 current fragment */ bool_t frag_sent; /* true if buffer sent in middle of record */ /* * in-coming bits */ - int (*readit) (caddr_t, caddr_t, int); + int (*readit)(void *, void *, 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; + + bool_t nonblock; + bool_t in_haveheader; + u_int32_t in_header; + char *in_hdrp; + int in_hdrlen; + int in_reclen; + int in_received; + int in_maxrec; } RECSTREAM; static u_int fix_buf_size(u_int); static bool_t flush_out(RECSTREAM *, bool_t); -static bool_t get_input_bytes(RECSTREAM *, caddr_t, int); +static bool_t fill_input_buf(RECSTREAM *); +static bool_t get_input_bytes(RECSTREAM *, char *, int); static bool_t set_input_fragment(RECSTREAM *); static bool_t skip_input_bytes(RECSTREAM *, long); - -static bool_t xdrrec_getlong(XDR *, long *); -static bool_t xdrrec_putlong(XDR *, long *); -static bool_t xdrrec_getbytes(XDR *, caddr_t, u_int); -static bool_t xdrrec_putbytes(XDR *, caddr_t, u_int); -static u_int xdrrec_getpos(XDR *); -static bool_t xdrrec_setpos(XDR *, u_int); -static int32_t *xdrrec_inline(XDR *, int); -static void xdrrec_destroy(XDR *); - -static struct xdr_ops xdrrec_ops = { - xdrrec_getlong, - xdrrec_putlong, - xdrrec_getbytes, - xdrrec_putbytes, - xdrrec_getpos, - xdrrec_setpos, - xdrrec_inline, - xdrrec_destroy -}; +static bool_t realloc_stream(RECSTREAM *, int); /* * Create an xdr handle for xdrrec @@ -137,45 +161,45 @@ static struct xdr_ops xdrrec_ops = { * writeit: lite write, but pass it a tcp_handle, not sock */ void -xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, caddr_t tcp_handle, - int (*readit)(caddr_t, caddr_t, int), - int (*writeit)(caddr_t, caddr_t, int)) +xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, void *tcp_handle, + int (*readit)(void *, void *, int), + int (*writeit)(void *, void *, int)) { - RECSTREAM *rstrm = - (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); + RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); if (rstrm == NULL) { - fprintf(stderr, "xdrrec_create: out of memory\n"); + warnx("xdrrec_create: out of memory"); /* * This is bad. Should rework xdrrec_create to * return a handle, and in this case return NULL */ return; } - /* - * adjust sizes and allocate buffer quad byte aligned - */ rstrm->sendsize = sendsize = fix_buf_size(sendsize); + rstrm->out_base = mem_alloc(rstrm->sendsize); + if (rstrm->out_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm, sizeof(RECSTREAM)); + return; + } rstrm->recvsize = recvsize = fix_buf_size(recvsize); - rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); - if (rstrm->the_buffer == NULL) { - fprintf(stderr, "xdrrec_create: out of memory\n"); + rstrm->in_base = mem_alloc(recvsize); + if (rstrm->in_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm->out_base, sendsize); + mem_free(rstrm, sizeof(RECSTREAM)); return; } - for (rstrm->out_base = rstrm->the_buffer; - (u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; - rstrm->out_base++); - rstrm->in_base = rstrm->out_base + sendsize; /* * 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; @@ -184,11 +208,17 @@ xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, caddr_t tcp_handle, rstrm->in_finger = (rstrm->in_boundry += recvsize); rstrm->fbtbc = 0; rstrm->last_frag = TRUE; + rstrm->in_haveheader = FALSE; + rstrm->in_hdrlen = 0; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->nonblock = FALSE; + rstrm->in_reclen = 0; + rstrm->in_received = 0; } /* - * The reoutines defined below are the xdr ops which will go into the + * The routines defined below are the xdr ops which will go into the * xdr handle filled in by xdrrec_create. */ @@ -196,7 +226,7 @@ static bool_t xdrrec_getlong(XDR *xdrs, long *lp) { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - int32_t *buflp = (int32_t *)(rstrm->in_finger); + int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger); int32_t mylong; /* first try the inline, fast case */ @@ -206,7 +236,8 @@ xdrrec_getlong(XDR *xdrs, long *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); } @@ -214,10 +245,10 @@ xdrrec_getlong(XDR *xdrs, long *lp) } static bool_t -xdrrec_putlong(XDR *xdrs, long *lp) +xdrrec_putlong(XDR *xdrs, const long *lp) { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - int32_t *dest_lp = ((int32_t *)(rstrm->out_finger)); + int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { /* @@ -228,7 +259,7 @@ xdrrec_putlong(XDR *xdrs, long *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)); @@ -236,13 +267,13 @@ xdrrec_putlong(XDR *xdrs, long *lp) } static bool_t /* must manage buffers, fragments, and records */ -xdrrec_getbytes(XDR *xdrs, caddr_t addr, u_int len) +xdrrec_getbytes(XDR *xdrs, char *addr, u_int len) { 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,16 +292,16 @@ xdrrec_getbytes(XDR *xdrs, caddr_t addr, u_int len) } static bool_t -xdrrec_putbytes(XDR *xdrs, caddr_t addr, u_int len) +xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len) { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - long current; + 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; @@ -287,9 +318,9 @@ static u_int xdrrec_getpos(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; - long pos; + 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) { @@ -302,7 +333,7 @@ xdrrec_getpos(XDR *xdrs) break; default: - pos = -1; + pos = (off_t) -1; break; } return ((u_int) pos); @@ -314,14 +345,14 @@ xdrrec_setpos(XDR *xdrs, u_int pos) 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); @@ -338,6 +369,7 @@ xdrrec_setpos(XDR *xdrs, u_int pos) return (TRUE); } break; + case XDR_FREE: break; } @@ -345,16 +377,16 @@ xdrrec_setpos(XDR *xdrs, u_int pos) } static int32_t * -xdrrec_inline(XDR *xdrs, int len) +xdrrec_inline(XDR *xdrs, u_int len) { RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; - int32_t * buf = NULL; + 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; @@ -362,7 +394,7 @@ xdrrec_inline(XDR *xdrs, int 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; } @@ -378,9 +410,9 @@ xdrrec_destroy(XDR *xdrs) { 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->out_base, rstrm->sendsize); + mem_free(rstrm->in_base, rstrm->recvsize); + mem_free(rstrm, sizeof(RECSTREAM)); } @@ -396,6 +428,20 @@ bool_t xdrrec_skiprecord(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + enum xprt_stat xstat; + + if (rstrm->nonblock) { + if (__xdrrec_getrec(xdrs, &xstat, FALSE)) { + rstrm->fbtbc = 0; + return TRUE; + } + if (rstrm->in_finger == rstrm->in_boundry && + xstat == XPRT_MOREREQS) { + rstrm->fbtbc = 0; + return TRUE; + } + return FALSE; + } while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { if (! skip_input_bytes(rstrm, rstrm->fbtbc)) @@ -409,7 +455,7 @@ xdrrec_skiprecord(XDR *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. */ @@ -450,12 +496,107 @@ xdrrec_endofrecord(XDR *xdrs, bool_t 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); } +/* + * Fill the stream buffer with a record for a non-blocking connection. + * Return true if a record is available in the buffer, false if not. + */ +bool_t +__xdrrec_getrec(XDR *xdrs, enum xprt_stat *statp, bool_t expectdata) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + ssize_t n; + int fraglen; + + if (!rstrm->in_haveheader) { + n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp, + (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen); + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_hdrp += n; + rstrm->in_hdrlen += n; + if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) { + *statp = XPRT_MOREREQS; + return FALSE; + } + rstrm->in_header = ntohl(rstrm->in_header); + fraglen = (int)(rstrm->in_header & ~LAST_FRAG); + if (fraglen == 0 || fraglen > rstrm->in_maxrec || + (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_reclen += fraglen; + if (rstrm->in_reclen > rstrm->recvsize) + realloc_stream(rstrm, rstrm->in_reclen); + if (rstrm->in_header & LAST_FRAG) { + rstrm->in_header &= ~LAST_FRAG; + rstrm->last_frag = TRUE; + } + /* + * We can only reasonably expect to read once from a + * non-blocking stream. Reading the fragment header + * may have drained the stream. + */ + expectdata = FALSE; + } + + n = rstrm->readit(rstrm->tcp_handle, + rstrm->in_base + rstrm->in_received, + (rstrm->in_reclen - rstrm->in_received)); + + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + + rstrm->in_received += n; + + if (rstrm->in_received == rstrm->in_reclen) { + rstrm->in_haveheader = FALSE; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->in_hdrlen = 0; + if (rstrm->last_frag) { + rstrm->fbtbc = rstrm->in_reclen; + rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen; + rstrm->in_finger = rstrm->in_base; + rstrm->in_reclen = rstrm->in_received = 0; + *statp = XPRT_MOREREQS; + return TRUE; + } + } + + *statp = XPRT_MOREREQS; + return FALSE; +} + +bool_t +__xdrrec_setnonblock(XDR *xdrs, int maxrec) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + rstrm->nonblock = TRUE; + if (maxrec == 0) + maxrec = rstrm->recvsize; + rstrm->in_maxrec = maxrec; + return TRUE; +} /* * Internal useful routines @@ -463,31 +604,35 @@ xdrrec_endofrecord(XDR *xdrs, bool_t sendnow) static bool_t flush_out(RECSTREAM *rstrm, bool_t eor) { - u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; - 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(RECSTREAM *rstrm) { - caddr_t where; - u_long i; - long len; + char *where; + u_int32_t i; + int len; + + if (rstrm->nonblock) + return FALSE; 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; @@ -497,19 +642,28 @@ fill_input_buf(RECSTREAM *rstrm) } static bool_t /* knows nothing about records! Only about input buffers */ -get_input_bytes(RECSTREAM *rstrm, caddr_t addr, int len) +get_input_bytes(RECSTREAM *rstrm, char *addr, int len) { - long current; + size_t current; + + if (rstrm->nonblock) { + if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) + return FALSE; + memcpy(addr, rstrm->in_finger, (size_t)len); + rstrm->in_finger += len; + return TRUE; + } 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; @@ -522,9 +676,11 @@ set_input_fragment(RECSTREAM *rstrm) { u_int32_t header; - if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) + if (rstrm->nonblock) + return FALSE; + 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 @@ -543,16 +699,17 @@ set_input_fragment(RECSTREAM *rstrm) static bool_t /* consumes input bytes; knows nothing about records! */ skip_input_bytes(RECSTREAM *rstrm, long cnt) { - 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; } @@ -567,3 +724,27 @@ fix_buf_size(u_int s) s = 4000; return (RNDUP(s)); } + +/* + * Reallocate the input buffer for a non-block stream. + */ +static bool_t +realloc_stream(RECSTREAM *rstrm, int size) +{ + ptrdiff_t diff; + char *buf; + + if (size > rstrm->recvsize) { + buf = realloc(rstrm->in_base, (size_t)size); + if (buf == NULL) + return FALSE; + diff = buf - rstrm->in_base; + rstrm->in_finger += diff; + rstrm->in_base = buf; + rstrm->in_boundry = buf + size; + rstrm->recvsize = size; + rstrm->in_size = size; + } + + return TRUE; +} diff --git a/lib/libc/xdr/xdr_reference.c b/lib/libc/xdr/xdr_reference.c index f63066bfa7..07a5f69054 100644 --- a/lib/libc/xdr/xdr_reference.c +++ b/lib/libc/xdr/xdr_reference.c @@ -28,7 +28,8 @@ * * @(#)xdr_reference.c 1.11 87/08/11 SMI * @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.8 1999/08/28 00:02:56 peter Exp $ + * $NetBSD: xdr_reference.c,v 1.13 2000/01/22 22:19:18 mycroft Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.12 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr_reference.c,v 1.4 2005/12/05 00:47:57 swildner Exp $ */ @@ -41,13 +42,15 @@ * "pointers". See xdr.h for more info on the interface to xdr. */ +#include "namespace.h" +#include #include #include #include + #include #include - -#define LASTUNSIGNED ((u_int) 0-1) +#include "libc_private.h" /* * XDR an indirect pointer @@ -77,17 +80,17 @@ xdr_reference(XDR *xdrs, caddr_t *pp, u_int size, xdrproc_t proc) case XDR_DECODE: *pp = loc = (caddr_t) mem_alloc(size); if (loc == NULL) { - 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; + case XDR_ENCODE: break; - } + } - stat = (*proc)(xdrs, loc, LASTUNSIGNED); + stat = (*proc)(xdrs, loc); if (xdrs->x_op == XDR_FREE) { mem_free(loc, size); diff --git a/lib/libc/xdr/xdr_sizeof.c b/lib/libc/xdr/xdr_sizeof.c index 199a92bc57..fd8d8ed717 100644 --- a/lib/libc/xdr/xdr_sizeof.c +++ b/lib/libc/xdr/xdr_sizeof.c @@ -5,27 +5,28 @@ * 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 * + * $FreeBSD: src/lib/libc/xdr/xdr_sizeof.c,v 1.5 2003/03/07 13:19:40 nectar Exp $ * $DragonFly: src/lib/libc/xdr/xdr_sizeof.c,v 1.2 2005/12/05 00:47:57 swildner Exp $ */ @@ -38,10 +39,12 @@ * when serialized using XDR. */ +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" /* ARGSUSED */ static bool_t @@ -74,7 +77,7 @@ x_setpostn(XDR *xdrs __unused, u_int pos __unused) } static int32_t * -x_inline(XDR *xdrs, long len) +x_inline(XDR *xdrs, u_int len) { if (len == 0) { return (NULL); @@ -82,7 +85,7 @@ x_inline(XDR *xdrs, long len) if (xdrs->x_op != XDR_ENCODE) { return (NULL); } - if (len < (long) xdrs->x_base) { + if (len < (u_int)xdrs->x_base) { /* x_private was already allocated */ xdrs->x_handy += len; return ((int32_t *) xdrs->x_private); diff --git a/lib/libc/xdr/xdr_stdio.c b/lib/libc/xdr/xdr_stdio.c index 7ed01142a8..cf0a27f70b 100644 --- a/lib/libc/xdr/xdr_stdio.c +++ b/lib/libc/xdr/xdr_stdio.c @@ -28,7 +28,8 @@ * * @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro * @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC - * $FreeBSD: src/lib/libc/xdr/xdr_stdio.c,v 1.7 1999/08/28 00:02:56 peter Exp $ + * $NetBSD: xdr_stdio.c,v 1.14 2000/01/22 22:19:19 mycroft Exp $ + * $FreeBSD: src/lib/libc/xdr/xdr_stdio.c,v 1.13 2004/10/16 06:32:43 obrien Exp $ * $DragonFly: src/lib/libc/xdr/xdr_stdio.c,v 1.4 2005/12/05 00:47:57 swildner Exp $ */ @@ -42,24 +43,27 @@ * from the stream. */ +#include "namespace.h" +#include + #include #include -#include #include +#include "un-namespace.h" +static void xdrstdio_destroy(XDR *); static bool_t xdrstdio_getlong(XDR *, long *); -static bool_t xdrstdio_putlong(XDR *, long *); -static bool_t xdrstdio_getbytes(XDR *, caddr_t, u_int); -static bool_t xdrstdio_putbytes(XDR *, caddr_t, u_int); +static bool_t xdrstdio_putlong(XDR *, const long *); +static bool_t xdrstdio_getbytes(XDR *, char *, u_int); +static bool_t xdrstdio_putbytes(XDR *, const char *, u_int); static u_int xdrstdio_getpos(XDR *); static bool_t xdrstdio_setpos(XDR *, u_int); static int32_t *xdrstdio_inline(XDR *, u_int); -static void xdrstdio_destroy(XDR *); /* * 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 */ @@ -81,7 +85,7 @@ xdrstdio_create(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; } @@ -94,46 +98,45 @@ static void xdrstdio_destroy(XDR *xdrs) { fflush((FILE *)xdrs->x_private); - /* xx should we close the file ?? */ + /* XXX: should we close the file ?? */ } static bool_t xdrstdio_getlong(XDR *xdrs, long *lp) { + u_int32_t temp; - if (fread((caddr_t)lp, sizeof(int32_t), 1, - (FILE *)xdrs->x_private) != 1) + if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) return (FALSE); - *lp = (long)ntohl((int32_t)*lp); + *lp = (long)ntohl(temp); return (TRUE); } static bool_t -xdrstdio_putlong(XDR *xdrs, long *lp) +xdrstdio_putlong(XDR *xdrs, const long *lp) { + int32_t mycopy = 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); } static bool_t -xdrstdio_getbytes(XDR *xdrs, caddr_t addr, u_int len) +xdrstdio_getbytes(XDR *xdrs, 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); } static bool_t -xdrstdio_putbytes(XDR *xdrs, caddr_t addr, u_int len) +xdrstdio_putbytes(XDR *xdrs, 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); } @@ -141,6 +144,7 @@ xdrstdio_putbytes(XDR *xdrs, caddr_t addr, u_int len) static u_int xdrstdio_getpos(XDR *xdrs) { + return ((u_int) ftell((FILE *)xdrs->x_private)); } @@ -152,6 +156,7 @@ xdrstdio_setpos(XDR *xdrs, u_int pos) FALSE : TRUE); } +/* ARGSUSED */ static int32_t * xdrstdio_inline(XDR *xdrs __unused, u_int len __unused) { diff --git a/lib/libc_rtld/Makefile b/lib/libc_rtld/Makefile index 8afecc8233..6584c5c308 100644 --- a/lib/libc_rtld/Makefile +++ b/lib/libc_rtld/Makefile @@ -5,6 +5,7 @@ INTERNALLIB= INSTALL_PIC_ARCHIVE= NOPROFILE= CFLAGS+=-I${.CURDIR}/../libc/include +CFLAGS+=-I${.CURDIR}/../libc/rpc CFLAGS+=-I${.CURDIR}/../../include -D__thread= AINC= -I${.OBJDIR} -I${.CURDIR}/../libc/${MACHINE_ARCH} diff --git a/lib/librpcsvc/rnusers.c b/lib/librpcsvc/rnusers.c index 5815544aea..ab24d45496 100644 --- a/lib/librpcsvc/rnusers.c +++ b/lib/librpcsvc/rnusers.c @@ -28,6 +28,7 @@ * Mountain View, California 94043 * * @(#)rnusers.c 1.2 91/03/11 TIRPC 1.0; from 1.7 89/03/24 SMI + * $FreeBSD: src/lib/librpcsvc/rnusers.c,v 1.3 2003/10/26 03:43:35 peter Exp $ * $DragonFly: src/lib/librpcsvc/rnusers.c,v 1.4 2007/11/25 14:33:02 swildner Exp $ */ @@ -46,8 +47,8 @@ int rusers(char *host, utmpidlearr *up) { return (callrpc(host, RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES, - xdr_void, (char *) NULL, - xdr_utmpidlearr, (char *) up)); + (xdrproc_t)xdr_void, (char *) NULL, + (xdrproc_t)xdr_utmpidlearr, (char *) up)); } int @@ -56,8 +57,8 @@ rnusers(char *host) int nusers; if (callrpc(host, RUSERSPROG, RUSERSVERS_ORIG, RUSERSPROC_NUM, - xdr_void, (char *) NULL, - xdr_u_long, (char *) &nusers) != 0) + (xdrproc_t)xdr_void, (char *) NULL, + (xdrproc_t)xdr_u_long, (char *) &nusers) != 0) return (-1); else return (nusers); diff --git a/lib/librpcsvc/rstat.c b/lib/librpcsvc/rstat.c index f10269aaed..f8b3b15b1b 100644 --- a/lib/librpcsvc/rstat.c +++ b/lib/librpcsvc/rstat.c @@ -28,6 +28,7 @@ * Mountain View, California 94043 * * @(#)rstat.c 1.2 91/03/11 TIRPC 1.0; from 1.6 89/03/24 SMI + * $FreeBSD: src/lib/librpcsvc/rstat.c,v 1.4 2003/10/26 03:43:35 peter Exp $ * $DragonFly: src/lib/librpcsvc/rstat.c,v 1.3 2007/11/25 14:33:02 swildner Exp $ */ @@ -41,12 +42,12 @@ #include #include -int +enum clnt_stat rstat(char *host, struct statstime *statp) { return (callrpc(host, RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, - xdr_void, (char *) NULL, - xdr_statstime, (char *) statp)); + (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_statstime, (char *) statp)); } int @@ -55,8 +56,8 @@ havedisk(char *host) long have; if (callrpc(host, RSTATPROG, RSTATVERS_SWTCH, RSTATPROC_HAVEDISK, - xdr_void, (char *) NULL, - xdr_long, (char *) &have) != 0) + (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_long, (char *) &have) != 0) return (-1); else return (have); diff --git a/lib/librpcsvc/rwall.c b/lib/librpcsvc/rwall.c index 14e4ab05e6..9a6517f4bf 100644 --- a/lib/librpcsvc/rwall.c +++ b/lib/librpcsvc/rwall.c @@ -28,6 +28,7 @@ * Mountain View, California 94043 * * @(#)rwall.c 1.2 91/03/11 TIRPC 1.0; from 1.3 89/03/24 SMI + * $FreeBSD: src/lib/librpcsvc/rwall.c,v 1.3 2003/10/26 03:43:35 peter Exp $ * $DragonFly: src/lib/librpcsvc/rwall.c,v 1.3 2007/11/25 14:33:02 swildner Exp $ */ @@ -45,6 +46,6 @@ int rwall(char *host, char *msg) { return (callrpc(host, WALLPROG, WALLVERS, WALLPROC_WALL, - xdr_wrapstring, (char *) &msg, - xdr_void, (char *) NULL)); + (xdrproc_t)xdr_wrapstring, (char *) &msg, + (xdrproc_t)xdr_void, (char *) NULL)); } diff --git a/lib/librpcsvc/secretkey.c b/lib/librpcsvc/secretkey.c index ec92009f88..ed75675f60 100644 --- a/lib/librpcsvc/secretkey.c +++ b/lib/librpcsvc/secretkey.c @@ -28,6 +28,7 @@ * Mountain View, California 94043 * * @(#)secretkey.c 1.8 91/03/11 Copyr 1986 Sun Micro + * $FreeBSD: src/lib/librpcsvc/secretkey.c,v 1.3 2002/03/21 23:53:40 obrien Exp $ * $DragonFly: src/lib/librpcsvc/secretkey.c,v 1.5 2007/11/25 14:33:02 swildner Exp $ */ @@ -47,7 +48,7 @@ #include #include -extern int xdecrypt ( char *, char * ); +extern int xdecrypt(char *, char *); /* * Get somebody's encrypted secret key from the database, using the given @@ -76,7 +77,7 @@ getsecretkey(char *netname, char *secretkey, char *passwd) return (1); } p[HEXKEYBYTES] = '\0'; - (void) strncpy(secretkey, p, HEXKEYBYTES); + strncpy(secretkey, p, HEXKEYBYTES); secretkey[HEXKEYBYTES] = '\0'; return (1); } diff --git a/lib/librpcsvc/xcrypt.c b/lib/librpcsvc/xcrypt.c index ebe540c84d..7ebef700aa 100644 --- a/lib/librpcsvc/xcrypt.c +++ b/lib/librpcsvc/xcrypt.c @@ -5,35 +5,35 @@ * 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 * * @(#)xcrypt.c 2.2 88/08/10 4.0 RPCSRC - * $FreeBSD: src/lib/librpcsvc/xcrypt.c,v 1.2 1999/08/28 00:05:24 peter Exp $ + * $FreeBSD: src/lib/librpcsvc/xcrypt.c,v 1.6 2008/02/04 07:56:36 matteo Exp $ * $DragonFly: src/lib/librpcsvc/xcrypt.c,v 1.4 2007/11/25 14:33:02 swildner Exp $ */ /* * Hex encryption/decryption and utility routines * - * Copyright (C) 1986, Sun Microsystems, Inc. + * Copyright (C) 1986, Sun Microsystems, Inc. */ #include @@ -42,11 +42,15 @@ #include #include -static char hex[]; /* forward */ -static char hexval ( char ); -static void bin2hex ( int, unsigned char *, char * ); -static void hex2bin ( int, char *, char * ); -void passwd2des ( char *, char * ); +static char hex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', +}; + +static void bin2hex(int, unsigned char *, char *); +static void hex2bin(int, char *, char *); +static char hexval(char); +void passwd2des(char *, char *); /* * Encrypt a secret key given passwd @@ -63,14 +67,15 @@ xencrypt(char *secret, char *passwd) int len; len = strlen(secret) / 2; - buf = malloc((unsigned)len); + if ((buf = malloc((unsigned)len)) == NULL) + return(0); hex2bin(len, secret, buf); passwd2des(passwd, key); bzero(ivec, 8); err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec); - if (DES_FAILED(err)) { + if (DES_FAILED(err)) { free(buf); return (0); } @@ -94,10 +99,11 @@ xdecrypt(char *secret, char *passwd) int len; len = strlen(secret) / 2; - buf = malloc((unsigned)len); + if ((buf = malloc((unsigned)len)) == NULL) + return(0); hex2bin(len, secret, buf); - passwd2des(passwd, key); + passwd2des(passwd, key); bzero(ivec, 8); err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec); @@ -158,11 +164,6 @@ bin2hex(int len, unsigned char *binnum, char *hexnum) hexnum[len*2] = 0; } -static char hex[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', -}; - static char hexval(char c) { diff --git a/lib/librpcsvc/yp_passwd.c b/lib/librpcsvc/yp_passwd.c index c20f201ea8..4db28b19f1 100644 --- a/lib/librpcsvc/yp_passwd.c +++ b/lib/librpcsvc/yp_passwd.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/librpcsvc/yp_passwd.c,v 1.2 1999/08/28 00:05:24 peter Exp $ + * $FreeBSD: src/lib/librpcsvc/yp_passwd.c,v 1.7 2003/10/26 03:43:35 peter Exp $ * $DragonFly: src/lib/librpcsvc/yp_passwd.c,v 1.3 2007/11/25 14:33:02 swildner Exp $ */ @@ -40,10 +40,6 @@ #include #include -#ifndef LINT -static const char rcsid[] = "$FreeBSD: src/lib/librpcsvc/yp_passwd.c,v 1.2 1999/08/28 00:05:24 peter Exp $"; -#endif - /* * XXX does a typedef that makes 'yppasswd' * a type of struct yppasswd. This leads to a namespace collision: @@ -54,7 +50,8 @@ static const char rcsid[] = "$FreeBSD: src/lib/librpcsvc/yp_passwd.c,v 1.2 1999/ * fooling gcc. */ -int _yppasswd(char *oldpass, struct x_passwd *newpw) +int +_yppasswd(char *oldpass, struct x_passwd *newpw) { char *server; char *domain; @@ -79,8 +76,8 @@ int _yppasswd(char *oldpass, struct x_passwd *newpw) } rval = callrpc(server, YPPASSWDPROG, YPPASSWDVERS, YPPASSWDPROC_UPDATE, - xdr_yppasswd, (char *)&yppasswd, xdr_int, - (char *)&result); + (xdrproc_t)xdr_yppasswd, (char *)&yppasswd, + (xdrproc_t)xdr_int, (char *)&result); free(server); if (rval || result) diff --git a/lib/librpcsvc/yp_update.c b/lib/librpcsvc/yp_update.c index 5817bcf7e4..3c14ed4187 100644 --- a/lib/librpcsvc/yp_update.c +++ b/lib/librpcsvc/yp_update.c @@ -35,10 +35,9 @@ * Center for Telecommunications Research * Columbia University, New York City * - * $FreeBSD: src/lib/librpcsvc/yp_update.c,v 1.2.2.1 2002/02/15 00:46:54 des Exp $ + * $FreeBSD: src/lib/librpcsvc/yp_update.c,v 1.7 2003/10/26 03:43:35 peter Exp $ * $DragonFly: src/lib/librpcsvc/yp_update.c,v 1.3 2007/11/25 14:33:02 swildner Exp $ * - * $FreeBSD: src/lib/librpcsvc/yp_update.c,v 1.2.2.1 2002/02/15 00:46:54 des Exp $ */ #include @@ -128,8 +127,9 @@ yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, upargs.datum.yp_buf_len = datalen; upargs.datum.yp_buf_val = data; - if ((rval = clnt_call(clnt, YPU_CHANGE, xdr_ypupdate_args, - &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if ((rval = clnt_call(clnt, YPU_CHANGE, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { if (rval == RPC_AUTHERROR) res = YPERR_ACCESS; else @@ -144,8 +144,9 @@ yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, upargs.datum.yp_buf_len = datalen; upargs.datum.yp_buf_val = data; - if ((rval = clnt_call(clnt, YPU_INSERT, xdr_ypupdate_args, - &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if ((rval = clnt_call(clnt, YPU_INSERT, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { if (rval == RPC_AUTHERROR) res = YPERR_ACCESS; else @@ -158,8 +159,9 @@ yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, delargs.key.yp_buf_len = keylen; delargs.key.yp_buf_val = key; - if ((rval = clnt_call(clnt, YPU_DELETE, xdr_ypdelete_args, - &delargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if ((rval = clnt_call(clnt, YPU_DELETE, + (xdrproc_t)xdr_ypdelete_args, &delargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { if (rval == RPC_AUTHERROR) res = YPERR_ACCESS; else @@ -174,8 +176,9 @@ yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, upargs.datum.yp_buf_len = datalen; upargs.datum.yp_buf_val = data; - if ((rval = clnt_call(clnt, YPU_STORE, xdr_ypupdate_args, - &upargs, xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if ((rval = clnt_call(clnt, YPU_STORE, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { if (rval == RPC_AUTHERROR) res = YPERR_ACCESS; else diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c index a2714b0c6f..571a051742 100644 --- a/sbin/mount_nfs/mount_nfs.c +++ b/sbin/mount_nfs/mount_nfs.c @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -57,13 +58,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include "mntopts.h" #include "mounttab.h" @@ -141,6 +142,19 @@ struct nfs_args nfsdefargs = { NFS_MAXDIRATTRTIMO, }; +/* Table for af,sotype -> netid conversions. */ +struct nc_protos { + const char *netid; + int af; + int sotype; +} nc_protos[] = { + {"udp", AF_INET, SOCK_DGRAM}, + {"tcp", AF_INET, SOCK_STREAM}, + {"udp6", AF_INET6, SOCK_DGRAM}, + {"tcp6", AF_INET6, SOCK_STREAM}, + {NULL, 0, 0} +}; + struct nfhret { u_long stat; long vers; @@ -148,16 +162,13 @@ struct nfhret { long fhsize; u_char nfh[NFSX_V3FHMAX]; }; - -#define BGRND 0x0001 -#define ISBGRND 0x0002 -#define DIDWARN 0x0004 - +#define BGRND 1 +#define ISBGRND 2 int retrycnt = -1; int opflags = 0; int nfsproto = IPPROTO_UDP; int mnttcp_ok = 1; -u_short port_no = 0; +char *portspec = NULL; /* Server nfs port; NULL means look up via rpcbind. */ enum mountmode { ANY, V2, @@ -187,14 +198,17 @@ enum tryret { TRYRET_LOCALERR /* Local failure. */ }; +#if 0 void set_rpc_maxgrouplist(int); - +#endif +static struct netconfig *getnetconf_cached(const char *); +static const char *netidbytype(int, int); static int getnfsargs(char *, struct nfs_args *); static void usage(void) __dead2; static int xdr_dir(XDR *, char *); static int xdr_fh(XDR *, struct nfhret *); static enum tryret - nfs_tryproto(struct nfs_args *, struct sockaddr_in *, + nfs_tryproto(struct nfs_args *, struct addrinfo *, char *, char *, char **); static enum tryret returncode(enum clnt_stat, struct rpc_err *); @@ -300,6 +314,7 @@ main(int argc, char **argv) case 'd': nfsargsp->flags |= NFSMNT_DUMBTIMR; break; +#if 0 /* XXXX */ case 'g': num = strtol(optarg, &p, 10); if (*p || num <= 0) @@ -308,6 +323,7 @@ main(int argc, char **argv) nfsargsp->maxgrouplist = num; nfsargsp->flags |= NFSMNT_MAXGRPS; break; +#endif case 'I': num = strtol(optarg, &p, 10); if (*p || num <= 0) @@ -356,8 +372,17 @@ main(int argc, char **argv) nfsargsp->sotype = SOCK_STREAM; nfsproto = IPPROTO_TCP; } - if(altflags & ALTF_PORT) - port_no = atoi(strstr(optarg, "port=") + 5); + if(altflags & ALTF_PORT) { + /* + * XXX Converting from a string to an int + * and back again is silly, and we should + * allow /etc/services names. + */ + asprintf(&portspec, "%d", + atoi(strstr(optarg, "port=") + 5)); + if (portspec == NULL) + err(1, "asprintf"); + } mountmode = ANY; if(altflags & ALTF_NFSV2) mountmode = V2; @@ -557,11 +582,12 @@ main(int argc, char **argv) static int getnfsargs(char *spec, struct nfs_args *nfsargsp) { - struct hostent *hp; - struct sockaddr_in saddr; - struct in_addr iaddr; + struct addrinfo hints, *ai_nfs, *ai; +#ifdef NFSKERB + char host[NI_MAXHOST], serv[NI_MAXSERV]; +#endif enum tryret ret; - int speclen, remoteerr; + int ecode, speclen, remoteerr; char *hostp, *delimp, *errstr; #ifdef NFSKERB char *cp; @@ -607,102 +633,60 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp) * Handle an internet host address and reverse resolve it if * doing Kerberos. */ - bzero(&saddr, sizeof saddr); - saddr.sin_family = AF_INET; - saddr.sin_len = sizeof saddr; - - if (port_no != 0) - saddr.sin_port = htons(port_no); - - for (;;) { - int haserror = 0; - - /* - * Adjust DNS timeouts so we do not linger in the foreground - * if we can be backgrounded. - */ - switch(opflags & (BGRND | ISBGRND)) { - case BGRND: - _res.retry = 1; - _res.retrans = 1; - break; - case BGRND|ISBGRND: - _res.retry = 3; - _res.retrans = 3; - break; - } - if (inet_pton(AF_INET, hostp, &iaddr) == 1) { - saddr.sin_addr = iaddr; - } else if ((hp = gethostbyname(hostp)) != NULL) { - memmove(&saddr.sin_addr, hp->h_addr, - MIN(hp->h_length, (int)sizeof(saddr.sin_addr))); - } else { - warnx("can't get net id for host: %s", hostp); - opflags |= DIDWARN; - haserror = h_errno; - } + memset(&hints, 0, sizeof hints); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_socktype = nfsargsp->sotype; + if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) == 0) { #ifdef NFSKERB - if (haserror == 0 && (nfsargsp->flags & NFSMNT_KERB)) { - if ((hp = gethostbyaddr(&saddr.sin_addr.s_addr, - sizeof (u_long), AF_INET)) == NULL) { + if ((nfsargsp->flags & NFSMNT_KERB)) { + hints.ai_flags = 0; + if (getnameinfo(ai_nfs->ai_addr, ai_nfs->ai_addrlen, + host, sizeof host, serv, sizeof serv, 0) != 0) { warnx("can't reverse resolve net address"); - opflags |= DIDWARN; - haserror = h_errno; - } else { - memmove(&saddr.sin_addr, hp->h_addr, - MIN(hp->h_length, sizeof(saddr.sin_addr))); - strncpy(inst, hp->h_name, INST_SZ); - inst[INST_SZ - 1] = '\0'; - if (cp = strchr(inst, '.')) - *cp = '\0'; - } + return (0); + } + hostp = host; } #endif /* NFSKERB */ - /* - * If no error occured we do not have to retry again. - * Otherwise try to backgruond us if possible. - */ - if (haserror == 0) - break; - - switch(opflags & (BGRND | ISBGRND)) { - case BGRND: - if (haserror != EAI_AGAIN) - return(0); - /* recoverable error */ - warnx("Cannot immediately mount %s:%s, backgrounding", - hostp, spec); - opflags |= DIDWARN; - opflags |= ISBGRND; - if (daemon(0, 0) != 0) - err(1, "daemon"); - break; - default: - /* - * Already backgrounded or cannot be backgrounded. - */ - if (haserror != EAI_AGAIN) - return(0); - break; + } else { + hints.ai_flags = 0; + if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs)) + != 0) { + if (portspec == NULL) + errx(1, "%s: %s", hostp, gai_strerror(ecode)); + else + errx(1, "%s:%s: %s", hostp, portspec, + gai_strerror(ecode)); + return (0); } - sleep(20); - endhostent(); } - if (opflags & DIDWARN) { - opflags &= ~DIDWARN; - warnx("successfully resolved %s after prior failures", hostp); +#ifdef NFSKERB + if (nfsargsp->flags & NFSMNT_KERB) { + strncpy(inst, hp->h_name, INST_SZ); + inst[INST_SZ - 1] = '\0'; + if (cp = strchr(inst, '.')) + *cp = '\0'; } +#endif /* NFSKERB */ ret = TRYRET_LOCALERR; for (;;) { + /* + * Try each entry returned by getaddrinfo(). Note the + * occurence of remote errors by setting `remoteerr'. + */ remoteerr = 0; - ret = nfs_tryproto(nfsargsp, &saddr, hostp, spec, &errstr); + for (ai = ai_nfs; ai != NULL; ai = ai->ai_next) { + ret = nfs_tryproto(nfsargsp, ai, hostp, spec, &errstr); + if (ret == TRYRET_SUCCESS) + break; + if (ret != TRYRET_LOCALERR) + remoteerr = 1; + if ((opflags & ISBGRND) == 0) + fprintf(stderr, "%s\n", errstr); + } if (ret == TRYRET_SUCCESS) break; - if (ret != TRYRET_LOCALERR) - remoteerr = 1; - if ((opflags & ISBGRND) == 0) - fprintf(stderr, "%s\n", errstr); /* Exit if all errors were local. */ if (!remoteerr) @@ -719,16 +703,12 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp) warnx("Cannot immediately mount %s:%s, backgrounding", hostp, spec); opflags |= ISBGRND; - opflags |= DIDWARN; if (daemon(0, 0) != 0) err(1, "daemon"); } - sleep(20); - } - if (opflags & DIDWARN) { - opflags &= ~DIDWARN; - warnx("successfully mounted %s after prior failures", spec); + sleep(60); } + freeaddrinfo(ai_nfs); nfsargsp->hostname = nam; /* Add mounted filesystem to PATH_MOUNTTAB */ if (!add_mtab(hostp, spec)) @@ -738,7 +718,7 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp) /* * Try to set up the NFS arguments according to the address - * (and possibly port) specified by `sinp'. + * family, protocol (and possibly port) specified in `ai'. * * Returns TRYRET_SUCCESS if successful, or: * TRYRET_TIMEOUT The server did not respond. @@ -749,23 +729,54 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp) * describing the error. */ static enum tryret -nfs_tryproto(struct nfs_args *nfsargsp, struct sockaddr_in *sinp, char *hostp, +nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp, char *spec, char **errstr) { static char errbuf[256]; - struct sockaddr_in sin, tmpsin; + struct sockaddr_storage nfs_ss; + struct netbuf nfs_nb; struct nfhret nfhret; struct timeval try; struct rpc_err rpcerr; CLIENT *clp; - int doconnect, nfsvers, mntvers, so; + struct netconfig *nconf, *nconf_mnt; + const char *netid, *netid_mnt; + int doconnect, nfsvers, mntvers; enum clnt_stat status; enum mountmode trymntmode; trymntmode = mountmode; errbuf[0] = '\0'; *errstr = errbuf; - sin = tmpsin = *sinp; + + if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) { + snprintf(errbuf, sizeof errbuf, + "af %d sotype %d not supported", ai->ai_family, + nfsargsp->sotype); + return (TRYRET_LOCALERR); + } + if ((nconf = getnetconf_cached(netid)) == NULL) { + snprintf(errbuf, sizeof errbuf, "%s: %s", netid, nc_sperror()); + return (TRYRET_LOCALERR); + } + /* The RPCPROG_MNT netid may be different. */ + if (mnttcp_ok) { + netid_mnt = netid; + nconf_mnt = nconf; + } else { + if ((netid_mnt = netidbytype(ai->ai_family, SOCK_DGRAM)) + == NULL) { + snprintf(errbuf, sizeof errbuf, + "af %d sotype SOCK_DGRAM not supported", + ai->ai_family); + return (TRYRET_LOCALERR); + } + if ((nconf_mnt = getnetconf_cached(netid_mnt)) == NULL) { + snprintf(errbuf, sizeof errbuf, "%s: %s", netid_mnt, + nc_sperror()); + return (TRYRET_LOCALERR); + } + } tryagain: if (trymntmode == V2) { @@ -776,16 +787,35 @@ tryagain: mntvers = 3; } + if (portspec != NULL) { + /* `ai' contains the complete nfsd sockaddr. */ + nfs_nb.buf = ai->ai_addr; + nfs_nb.len = nfs_nb.maxlen = ai->ai_addrlen; + } else { + /* Ask the remote rpcbind. */ + nfs_nb.buf = &nfs_ss; + nfs_nb.len = nfs_nb.maxlen = sizeof nfs_ss; + + if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, + hostp)) { + if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH && + trymntmode == ANY) { + trymntmode = V2; + goto tryagain; + } + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", + netid, hostp, spec, + clnt_spcreateerror("RPCPROG_NFS")); + return (returncode(rpc_createerr.cf_stat, + &rpc_createerr.cf_error)); + } + } + /* Check that the server (nfsd) responds on the port we have chosen. */ - try.tv_sec = 10; - try.tv_usec = 0; - so = RPC_ANYSOCK; - if (nfsargsp->sotype == SOCK_STREAM) - clp = clnttcp_create(&sin, RPCPROG_NFS, nfsvers, &so, 0, 0); - else - clp = clntudp_create(&sin, RPCPROG_NFS, nfsvers, try, &so); + clp = clnt_tli_create(RPC_ANYFD, nconf, &nfs_nb, RPCPROG_NFS, nfsvers, + 0, 0); if (clp == NULL) { - snprintf(errbuf, sizeof errbuf, "%s:%s: %s", + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid, hostp, spec, clnt_spcreateerror("nfsd: RPCPROG_NFS")); return (returncode(rpc_createerr.cf_stat, &rpc_createerr.cf_error)); @@ -801,15 +831,16 @@ tryagain: if (!clnt_control(clp, CLSET_CONNECT, (char *)&doconnect)) { clnt_destroy(clp); snprintf(errbuf, sizeof errbuf, - "%s:%s: CLSET_CONNECT failed", hostp, spec); + "[%s] %s:%s: CLSET_CONNECT failed", netid, hostp, + spec); return (TRYRET_LOCALERR); } } try.tv_sec = 10; try.tv_usec = 0; - status = clnt_call(clp, NFSPROC_NULL, xdr_void, NULL, xdr_void, NULL, - try); + status = clnt_call(clp, NFSPROC_NULL, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_void, NULL, try); if (status != RPC_SUCCESS) { if (status == RPC_PROGVERSMISMATCH && trymntmode == ANY) { clnt_destroy(clp); @@ -817,7 +848,7 @@ tryagain: goto tryagain; } clnt_geterr(clp, &rpcerr); - snprintf(errbuf, sizeof errbuf, "%s:%s: %s", + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid, hostp, spec, clnt_sperror(clp, "NFSPROC_NULL")); clnt_destroy(clp); return (returncode(status, &rpcerr)); @@ -825,28 +856,23 @@ tryagain: clnt_destroy(clp); /* Send the RPCMNT_MOUNT RPC to get the root filehandle. */ - tmpsin.sin_port = 0; try.tv_sec = 10; try.tv_usec = 0; - so = RPC_ANYSOCK; - if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) - clp = clnttcp_create(&tmpsin, RPCPROG_MNT, mntvers, &so, 0, 0); - else - clp = clntudp_create(&tmpsin, RPCPROG_MNT, mntvers, try, &so); + clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers, nconf_mnt); if (clp == NULL) { - snprintf(errbuf, sizeof errbuf, "%s:%s: %s", + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, hostp, spec, clnt_spcreateerror("RPCMNT: clnt_create")); return (returncode(rpc_createerr.cf_stat, &rpc_createerr.cf_error)); } - clp->cl_auth = authunix_create_default(); + clp->cl_auth = authsys_create_default(); if (nfsargsp->flags & NFSMNT_KERB) nfhret.auth = RPCAUTH_KERB4; else nfhret.auth = RPCAUTH_UNIX; nfhret.vers = mntvers; - status = clnt_call(clp, RPCMNT_MOUNT, xdr_dir, spec, xdr_fh, &nfhret, - try); + status = clnt_call(clp, RPCMNT_MOUNT, (xdrproc_t)xdr_dir, spec, + (xdrproc_t)xdr_fh, &nfhret, try); auth_destroy(clp->cl_auth); if (status != RPC_SUCCESS) { if (status == RPC_PROGVERSMISMATCH && trymntmode == ANY) { @@ -855,7 +881,7 @@ tryagain: goto tryagain; } clnt_geterr(clp, &rpcerr); - snprintf(errbuf, sizeof errbuf, "%s:%s: %s", + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, hostp, spec, clnt_sperror(clp, "RPCPROG_MNT")); clnt_destroy(clp); return (returncode(status, &rpcerr)); @@ -863,7 +889,7 @@ tryagain: clnt_destroy(clp); if (nfhret.stat != 0) { - snprintf(errbuf, sizeof errbuf, "%s:%s: %s", + snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt, hostp, spec, strerror(nfhret.stat)); return (TRYRET_REMOTEERR); } @@ -872,13 +898,13 @@ tryagain: * Store the filehandle and server address in nfsargsp, making * sure to copy any locally allocated structures. */ - nfsargsp->addrlen = sin.sin_len; + nfsargsp->addrlen = nfs_nb.len; nfsargsp->addr = malloc(nfsargsp->addrlen); nfsargsp->fhsize = nfhret.fhsize; nfsargsp->fh = malloc(nfsargsp->fhsize); if (nfsargsp->addr == NULL || nfsargsp->fh == NULL) err(1, "malloc"); - bcopy(&sin, nfsargsp->addr, nfsargsp->addrlen); + bcopy(nfs_nb.buf, nfsargsp->addr, nfsargsp->addrlen); bcopy(nfhret.nfh, nfsargsp->fh, nfsargsp->fhsize); if (nfsvers == 3) @@ -889,6 +915,7 @@ tryagain: return (TRYRET_SUCCESS); } + /* * Catagorise a RPC return status and error into an `enum tryret' * return code. @@ -922,6 +949,57 @@ returncode(enum clnt_stat status, struct rpc_err *rpcerr) return (TRYRET_LOCALERR); } +/* + * Look up a netid based on an address family and socket type. + * `af' is the address family, and `sotype' is SOCK_DGRAM or SOCK_STREAM. + * + * XXX there should be a library function for this. + */ +static const char * +netidbytype(int af, int sotype) +{ + struct nc_protos *p; + + for (p = nc_protos; p->netid != NULL; p++) { + if (af != p->af || sotype != p->sotype) + continue; + return (p->netid); + } + return (NULL); +} + +/* + * Look up a netconfig entry based on a netid, and cache the result so + * that we don't need to remember to call freenetconfigent(). + * + * Otherwise it behaves just like getnetconfigent(), so nc_*error() + * work on failure. + */ +static struct netconfig * +getnetconf_cached(const char *netid) +{ + static struct nc_entry { + struct netconfig *nconf; + struct nc_entry *next; + } *head; + struct nc_entry *p; + struct netconfig *nconf; + + for (p = head; p != NULL; p = p->next) + if (strcmp(netid, p->nconf->nc_netid) == 0) + return (p->nconf); + + if ((nconf = getnetconfigent(netid)) == NULL) + return (NULL); + if ((p = malloc(sizeof(*p))) == NULL) + err(1, "malloc"); + p->nconf = nconf; + p->next = head; + head = p; + + return (p->nconf); +} + /* * xdr routines for mount rpc's */ diff --git a/sbin/mountd/Makefile b/sbin/mountd/Makefile index f9f371039a..6c32d743d1 100644 --- a/sbin/mountd/Makefile +++ b/sbin/mountd/Makefile @@ -5,6 +5,6 @@ PROG= mountd CFLAGS+=-DNFS -DMFS -DCD9660 -DMSDOSFS MAN= exports.5 netgroup.5 mountd.8 -WARNS?= 2 +WARNS?= 0 .include diff --git a/sbin/mountd/mountd.c b/sbin/mountd/mountd.c index fc91ac8d5b..c6b4291635 100644 --- a/sbin/mountd/mountd.c +++ b/sbin/mountd/mountd.c @@ -42,12 +42,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -75,6 +78,10 @@ #include #endif +#ifndef MOUNTDLOCK +#define MOUNTDLOCK "/var/run/mountd.lock" +#endif + /* * Structures for keeping the mount list and export list */ @@ -109,13 +116,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; }; @@ -128,6 +135,7 @@ struct grouplist { #define GT_NULL 0x0 #define GT_HOST 0x1 #define GT_NET 0x2 +#define GT_DEFAULT 0x3 #define GT_IGNORE 0x5 struct hostlist { @@ -149,7 +157,7 @@ void add_dlist(struct dirlist **, struct dirlist *, void add_mlist(char *, char *); int check_dirpath(char *); int check_options(struct dirlist *); -int chk_host(struct dirlist *, u_int32_t, int *, int *); +int chk_host(struct dirlist *, struct sockaddr *, int *, int *); void del_mlist(char *, char *); struct dirlist *dirp_search(struct dirlist *, char *); int do_mount(struct exportlist *, struct grouplist *, int, @@ -164,7 +172,6 @@ void free_grp(struct grouplist *); void free_host(struct hostlist *); void get_exportlist(void); int get_host(char *, struct grouplist *, struct grouplist *); -int get_num(char *); struct hostlist *get_ht(void); int get_line(void); void get_mountlist(void); @@ -173,17 +180,25 @@ void getexp_err(struct exportlist *, struct grouplist *); struct grouplist *get_grp(void); void hang_dirp(struct dirlist *, struct grouplist *, struct exportlist *, int); +void huphandler(int sig); void mntsrv(struct svc_req *, SVCXPRT *); void nextfield(char **, char **); void out_of_mem(void); void parsecred(char *, struct ucred *); int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *); -int scan_tree(struct dirlist *, u_int32_t); +int scan_tree(struct dirlist *, struct sockaddr *); static void usage(void); int xdr_dir(XDR *, char *); int xdr_explist(XDR *, caddr_t); int xdr_fhs(XDR *, caddr_t); int xdr_mlist(XDR *, caddr_t); +void terminate(int); + +static int allones(struct sockaddr_storage *, int); +static int bitcmp(void *, void *, int); +static int countones(struct sockaddr *); +static int netpartcmp(struct sockaddr *, struct sockaddr *, int); +static int sacmp(struct sockaddr *, struct sockaddr *); struct exportlist *exphead; struct mountlist *mlhead; @@ -199,7 +214,17 @@ int force_v2 = 0; int resvport_only = 1; int dir_only = 1; int do_log = 0; +int got_sighup = 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 @@ -209,6 +234,7 @@ int opt_flags; #define OP_ALLDIRS 0x40 /* 0x80 is OP_HAVEMASK in FreeBSD 5+ */ #define OP_QUIET 0x100 +#define OP_MASKLEN 0x200 #ifdef DEBUG int debug = 1; @@ -228,10 +254,29 @@ int debug = 0; int main(int argc, char **argv) { - SVCXPRT *udptransp, *tcptransp; + fd_set readfds; + 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; + udp6conf = tcp6conf = NULL; + udp6sock = tcp6sock = NULL; + + /* 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")) @@ -286,13 +331,43 @@ main(int argc, char **argv) signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); } - signal(SIGHUP, (void (*)(int)) get_exportlist); + signal(SIGHUP, huphandler); + 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); + udpconf = getnetconfigent("udp"); + tcpconf = getnetconfigent("tcp"); + if (!have_v6) + goto skip_v6; + 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); + } + udp6conf = getnetconfigent("udp6"); + tcp6conf = getnetconfigent("tcp6"); + +skip_v6: if (!resvport_only) { mib[0] = CTL_VFS; mib[1] = vfc.vfc_typenum; @@ -308,22 +383,112 @@ main(int argc, char **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"); + 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 (have_v6 && 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 (have_v6 && 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); + } + + /* Expand svc_run() here so that we can call get_exportlist(). */ + for (;;) { + if (got_sighup) { + get_exportlist(); + got_sighup = 0; + } + readfds = svc_fdset; + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { + case -1: + if (errno == EINTR) + continue; + syslog(LOG_ERR, "mountd died: select: %m"); exit(1); + case 0: + continue; + default: + svc_getreqset(&readfds); } - 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"); - exit(1); } - svc_run(); - syslog(LOG_ERR, "mountd died"); - exit(1); } static void @@ -345,9 +510,10 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *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; @@ -355,10 +521,23 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) 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: + sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); + break; + case AF_INET: + sport = ntohs(((struct sockaddr_in *)saddr)->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)) @@ -368,13 +547,13 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *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; } @@ -387,12 +566,12 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *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 */ @@ -404,9 +583,9 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *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)) @@ -432,25 +611,21 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) } if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) syslog(LOG_ERR, "can't send reply"); - if (hp == NULL) - hp = gethostbyaddr(&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 (do_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)) @@ -463,56 +638,54 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) else if (do_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(&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); + del_mlist(numerichost, dirpath); if (do_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(&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); + del_mlist(numerichost, NULL); if (do_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)) @@ -520,7 +693,7 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) if (do_log) syslog(LOG_NOTICE, "export request succeeded from %s", - inet_ntoa(saddrin)); + numerichost); return; default: svcerr_noproc(transp); @@ -662,7 +835,7 @@ put_exlist(struct dirlist *dp, XDR *xdrsp, struct dirlist *adp, int *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); @@ -704,7 +877,6 @@ get_exportlist(void) struct exportlist **epp; struct dirlist *dirhead; struct statfs fsb, *fsp; - struct hostent *hpe; struct ucred anon; char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; @@ -762,7 +934,7 @@ get_exportlist(void) 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++; } @@ -850,9 +1022,9 @@ get_exportlist(void) 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], @@ -916,18 +1088,9 @@ get_exportlist(void) goto nextline; } if (!has_host) { - grp->gr_type = GT_HOST; + grp->gr_type = GT_DEFAULT; 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; /* * Don't allow a network export coincide with a list of @@ -937,13 +1100,13 @@ get_exportlist(void) 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); @@ -958,11 +1121,11 @@ get_exportlist(void) */ grp = tgrp; do { - if (do_mount(ep, grp, exflags, &anon, dirp, - dirplen, &fsb)) { - getexp_err(ep, tgrp); - goto nextline; - } + if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, + &fsb)) { + getexp_err(ep, tgrp); + goto nextline; + } } while (grp->gr_next && (grp = grp->gr_next)); /* @@ -1185,31 +1348,73 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp, * Search for a dirpath on the export point. */ struct dirlist * -dirp_search(struct dirlist *dp, char *dirpath) +dirp_search(struct dirlist *dp, 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); } return (dp); } +/* + * 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(struct dirlist *dp, u_int32_t saddr, int *defsetp, int *hostsetp) +chk_host(struct dirlist *dp, 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) @@ -1219,22 +1424,22 @@ chk_host(struct dirlist *dp, u_int32_t saddr, int *defsetp, int *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; @@ -1247,7 +1452,7 @@ chk_host(struct dirlist *dp, u_int32_t saddr, int *defsetp, int *hostsetp) * Scan tree for a host that matches the address. */ int -scan_tree(struct dirlist *dp, u_int32_t saddr) +scan_tree(struct dirlist *dp, struct sockaddr *saddr) { int defset, hostset; @@ -1343,6 +1548,11 @@ do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, 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); @@ -1392,84 +1602,56 @@ int get_host(char *cp, struct grouplist *grp, struct grouplist *tgrp) { struct grouplist *checkgrp; - struct hostent *hp, *nhp; - char **addrp, **naddrp; - struct hostent t_host; - int i; - u_int32_t saddr; - char *aptr[2]; + struct addrinfo *ai, *tai, hints; + int ecode; + char host[NI_MAXHOST]; - 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(&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; + } + 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_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; + } + if (debug) + fprintf(stderr, "got host %s\n", ai->ai_canonname); + /* + * Sanity check: make sure we don't already have an entry + * for this host in the grouplist. + */ + for (checkgrp = tgrp; checkgrp != NULL; + checkgrp = checkgrp->gr_next) { + if (checkgrp->gr_type != GT_HOST) + continue; + for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; + tai = tai->ai_next) { + if (sacmp(tai->ai_addr, ai->ai_addr) != 0) + continue; + if (debug) + fprintf(stderr, + "ignoring duplicate host %s\n", + ai->ai_canonname); + grp->gr_type = GT_IGNORE; + return (0); } - } else { - syslog(LOG_ERR, "gethostbyname failed for %s", cp); - return (1); } + ai = ai->ai_next; } - /* - * 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; - } - 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); return (0); } @@ -1540,68 +1722,65 @@ do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, struct ucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb) { struct statfs fsb1; + struct sockaddr_storage ss; + struct addrinfo *ai; char *cp = NULL; - u_int32_t **addrp; 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; + ai = grp->gr_ptr.gt_addrinfo; else - addrp = (u_int32_t **)NULL; + ai = 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 (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) + goto skip; + args.ua.export.ex_addr = ai->ai_addr; + args.ua.export.ex_addrlen = ai->ai_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_DEFAULT: + args.ua.export.ex_addr = NULL; + args.ua.export.ex_addrlen = 0; + args.ua.export.ex_mask = NULL; + args.ua.export.ex_masklen = 0; break; case GT_IGNORE: return(0); @@ -1641,6 +1820,9 @@ do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, if (opt_flags & OP_QUIET) return (1); if (errno == EPERM) { + if (debug) + warnx("can't change attributes for %s", + dirp); syslog(LOG_ERR, "can't change attributes for %s", dirp); return (1); @@ -1677,11 +1859,10 @@ do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, return (1); } } - if (addrp) { - ++addrp; - if (*addrp == (u_int32_t *)NULL) - done = TRUE; - } else +skip: + if (ai != NULL) + ai = ai->ai_next; + if (ai == NULL) done = TRUE; } if (cp) @@ -1696,47 +1877,106 @@ int get_net(char *cp, struct netmsk *net, 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; + + p = prefp = NULL; + 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; } /* @@ -1999,17 +2239,9 @@ add_mlist(char *hostp, char *dirp) void free_grp(struct grouplist *grp) { - char **addrp; - 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); @@ -2057,7 +2289,6 @@ check_options(struct dirlist *dp) /* * Check an absolute directory path for any symbolic links. Return true - * if no symbolic links are found. */ int check_dirpath(char *dirp) @@ -2081,18 +2312,151 @@ check_dirpath(char *dirp) return (ret); } -/* - * Just translate an ascii string to an integer. - */ -int -get_num(char *cp) +static int +netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen) { - int res = 0; + 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; + } - while (*cp) { - if (*cp < '0' || *cp > '9') - return (-1); - res = res * 10 + (*cp++ - '0'); + 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; } - return (res); + + 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 +huphandler(int sig) +{ + got_sighup = 1; +} + +void terminate(sig) +int sig; +{ + close(mountdlockfd); + unlink(MOUNTDLOCK); + rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); + rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); + exit (0); } diff --git a/sbin/nfsd/nfsd.8 b/sbin/nfsd/nfsd.8 index ad02eea85e..e692213356 100644 --- a/sbin/nfsd/nfsd.8 +++ b/sbin/nfsd/nfsd.8 @@ -9,10 +9,6 @@ .\" 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. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)nfsd.8 8.4 (Berkeley) 3/29/95 -.\" $FreeBSD: src/sbin/nfsd/nfsd.8,v 1.12.2.3 2002/05/20 18:06:11 gordon Exp $ +.\" $FreeBSD: src/usr.sbin/nfsd/nfsd.8,v 1.24 2005/01/17 07:44:42 ru Exp $ .\" $DragonFly: src/sbin/nfsd/nfsd.8,v 1.4 2007/11/23 23:16:36 swildner Exp $ .\" .Dd March 29, 1995 @@ -43,12 +39,13 @@ server .Sh SYNOPSIS .Nm -.Op Fl arut +.Op Fl ardut .Op Fl n Ar num_servers .Op Fl h Ar bindip .Sh DESCRIPTION -.Nm Nfsd -runs on a server machine to service +The +.Nm +utility runs on a server machine to service .Tn NFS requests from client machines. At least one @@ -65,13 +62,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 @@ -84,9 +87,11 @@ options may be specified. Specifies that nfsd should bind to the wildcard IP address. This is the default if no .Fl h -options are given. It may also be specified in addition to any +options are given. +It may also be specified in addition to any .Fl h -options given. Note that NFS/UDP does not operate properly when +options given. +Note that NFS/UDP does not operate properly when bound to the wildcard IP address whether you use -a or do not use -h. .It Fl t Serve @@ -110,8 +115,9 @@ A server should run enough daemons to handle the maximum level of concurrency from its clients, typically four to six. .Pp -.Nm Nfsd -listens for service requests at the port indicated in the +The +.Nm +utility listens for service requests at the port indicated in the .Tn NFS server specification; see .%T "Network File System Protocol Specification" , @@ -126,9 +132,7 @@ is not loaded in the running kernel, it will attempt to load a loadable kernel module containing .Tn NFS support using -.Xr kldload 8 -by way of -.Xr vfsload 3 . +.Xr kldload 2 . If this fails, or no .Tn NFS KLD is available, @@ -140,41 +144,46 @@ If is to be run on a host with multiple interfaces or interface aliases, use of the .Fl h -option is recommended. If you do not use the option NFS may not respond to -UDP packets from the same IP address they were sent to. Use of this option +option is recommended. +If you do not use the option NFS may not respond to +UDP packets from the same IP address they were sent to. +Use of this option is also recommended when securing NFS exports on a firewalling machine such that the NFS sockets can only be accessed by the inside interface. -.Nm Ipfw +The +.Nm ipfw +utility would then be used to block nfs-related packets that come in on the outside interface. .Pp +The .Nm -has to be terminated with +utility has to be terminated with .Dv SIGUSR1 and cannot be killed with .Dv SIGTERM or .Dv SIGQUIT . +The .Nm -needs to ignore these signals in order to stay alive as long +utility 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 " -.Pp -The -.Nm -utility exits 0 on success, and >0 if an error occurs. +.Sh EXIT STATUS +.Ex -std .Sh SEE ALSO .Xr nfsstat 1 , +.Xr kldload 2 , .Xr nfssvc 2 , +.Xr exports 5 , .Xr ipfw 8 , -.Xr kldload 8 , .Xr mountd 8 , .Xr nfsiod 8 , -.Xr portmap 8 +.Xr rpcbind 8 .Sh HISTORY The .Nm diff --git a/sbin/nfsd/nfsd.c b/sbin/nfsd/nfsd.c index d649139f49..71c493e7d0 100644 --- a/sbin/nfsd/nfsd.c +++ b/sbin/nfsd/nfsd.c @@ -13,10 +13,6 @@ * 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. @@ -35,7 +31,7 @@ * * @(#) Copyright (c) 1989, 1993, 1994 The Regents of the University of California. All rights reserved. * @(#)nfsd.c 8.9 (Berkeley) 3/29/95 - * $FreeBSD: src/sbin/nfsd/nfsd.c,v 1.15.2.1 2000/09/16 22:52:23 brian Exp $ + * $FreeBSD: src/usr.sbin/nfsd/nfsd.c,v 1.34 2005/12/21 10:12:05 delphij Exp $ * $DragonFly: src/sbin/nfsd/nfsd.c,v 1.10 2006/12/27 23:06:29 corecode Exp $ */ @@ -43,51 +39,52 @@ #include #include #include +#include +#include #include #include #include #include -#ifdef ISO -#include -#endif #include #include #include #include #include +#include #include #include -#include +#include #include +#include /* Global defs */ #ifdef DEBUG -#define syslog(e, s) fprintf(stderr,(s)) +#define syslog(e, s...) fprintf(stderr,s) int debug = 1; #else int debug = 0; #endif -struct nfsd_srvargs nsd; - -#ifdef NFSKERB -char lnam[ANAME_SZ]; -KTEXT_ST kt; -AUTH_DAT kauth; -char inst[INST_SZ]; -struct nfsrpc_fullblock kin, kout; -struct nfsrpc_fullverf kverf; -NFSKERBKEY_T kivec; -struct timeval ktv; -NFSKERBKEYSCHED_T kerb_keysched; -#endif +struct nfsd_srvargs nsd; + +#define MAXNFSDCNT 256 +#define DEFNFSDCNT 4 +pid_t children[MAXNFSDCNT]; /* PIDs of children */ +int nfsdcnt; /* number of children */ +void cleanup(int); +void child_cleanup(int); +void killchildren(void); +void nfsd_exit(int); void nonfs(int); void reapchild(int); -void setbindhost(struct sockaddr_in *ia, const char *bindhost); +int setbindhost(struct addrinfo **ia, const char *bindhost, + struct addrinfo hints); +void start_server(int); +void unregistration(void); void usage(void); /* @@ -96,15 +93,15 @@ void usage(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(). * For connection based sockets, loop doing accepts. When you get a new * 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 @@ -113,27 +110,21 @@ int main(int argc, char **argv) { 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; - int ch, cltpflag, connect_type_cnt, i, len, maxsock = -1, msgsock; - int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock = -1; - int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag; - int bindhostc = 0, bindanyflag; + fd_set v4bits, v6bits; + int ch, connect_type_cnt, i, maxsock, msgsock; + socklen_t len; + int on = 1, unregister, reregister, sock; + int tcp6sock, ip6flag, tcpflag, tcpsock; + int udpflag, ecode, s, srvcnt; + int bindhostc, bindanyflag, rpcbreg, rpcbregcnt; char **bindhost = NULL; -#ifdef notyet - int tp4sock, tpipsock; -#endif -#ifdef NFSKERB - struct group *grp; - struct passwd *pwd; - struct ucred *cr; - struct timeval ktv; - char **cpp; -#endif + pid_t pid; struct vfsconf vfc; int error; @@ -147,18 +138,11 @@ main(int argc, char **argv) if (error) errx(1, "NFS is not available in the running kernel"); -#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 + unregister = reregister = tcpflag = maxsock = 0; + bindanyflag = udpflag = connect_type_cnt = bindhostc = 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': @@ -175,7 +159,7 @@ main(int argc, char **argv) case 'h': bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); - if (bindhost == NULL) + if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup(optarg); if (bindhost[bindhostc-1] == NULL) @@ -184,25 +168,15 @@ main(int argc, char **argv) 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(); @@ -227,319 +201,446 @@ main(int argc, char **argv) } } + ip6flag = 1; + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s == -1) { + if (errno != EPROTONOSUPPORT) + err(1, "socket"); + ip6flag = 0; + } else if (getnetconfigent("udp6") == NULL || + getnetconfigent("tcp6") == NULL) { + ip6flag = 0; + } + if (s != -1) + close(s); + if (bindhostc == 0 || bindanyflag) { bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); - if (bindhost == NULL) + if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup("*"); - if (bindhost[bindhostc-1] == NULL) + if (bindhost[bindhostc-1] == NULL) errx(1, "Out of memory"); } + if (unregister) { + unregistration(); + exit (0); + } + if (reregister) { + 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) + err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); + 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) + err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); + 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) + err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); + 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) + err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); + 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); + } if (debug == 0) { daemon(0, 0); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGSYS, nonfs); + /* + * 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. + */ signal(SIGTERM, SIG_IGN); + signal(SIGQUIT, SIG_IGN); } + signal(SIGSYS, nonfs); signal(SIGCHLD, reapchild); - 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); - } - openlog("nfsd:", LOG_PID, LOG_DAEMON); + openlog("nfsd", LOG_PID, LOG_DAEMON); - for (i = 0; i < nfsdcnt; i++) { - switch (fork()) { + /* If we use UDP only, we start the last server below. */ + srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1; + for (i = 0; i < srvcnt; i++) { + switch ((pid = fork())) { case -1: syslog(LOG_ERR, "fork: %m"); - exit (1); + nfsd_exit(1); case 0: break; default: + children[i] = pid; continue; } - + signal(SIGUSR1, child_cleanup); setproctitle("server"); - nfssvc_flag = NFSSVC_NFSD; - nsd.nsd_nfsd = NULL; -#ifdef NFSKERB - if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || - sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) - syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); - nsd.nsd_authstr = (u_char *)&kt; - nsd.nsd_authlen = sizeof (kt); - nsd.nsd_verfstr = (u_char *)&kverf; - nsd.nsd_verflen = sizeof (kverf); -#endif - while (nfssvc(nfssvc_flag, &nsd) < 0) { - if (errno != ENEEDAUTH) { - syslog(LOG_ERR, "nfssvc: %m"); - exit(1); - } - nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; -#ifdef NFSKERB - /* - * Get the Kerberos ticket out of the authenticator - * verify it and convert the principal name to a user - * name. The user name is then converted to a set of - * user credentials via the password and group file. - * Finally, decrypt the timestamp and validate it. - * For more info see the IETF Draft "Authentication - * in ONC RPC". - */ - kt.length = ntohl(kt.length); - if (gettimeofday(&ktv, (struct timezone *)0) == 0 && - kt.length > 0 && kt.length <= - (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { - kin.w1 = NFS_KERBW1(kt); - kt.mbz = 0; - strcpy(inst, "*"); - if (krb_rd_req(&kt, NFS_KERBSRV, - inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && - krb_kntoln(&kauth, lnam) == KSUCCESS && - (pwd = getpwnam(lnam)) != NULL) { - cr = &nsd.nsd_cr; - cr->cr_uid = pwd->pw_uid; - cr->cr_groups[0] = pwd->pw_gid; - cr->cr_ngroups = 1; - setgrent(); - while ((grp = getgrent()) != NULL) { - if (grp->gr_gid == cr->cr_groups[0]) - continue; - for (cpp = grp->gr_mem; - *cpp != NULL; ++cpp) - if (!strcmp(*cpp, lnam)) - break; - if (*cpp == NULL) - continue; - cr->cr_groups[cr->cr_ngroups++] - = grp->gr_gid; - if (cr->cr_ngroups == NGROUPS) - break; - } - endgrent(); - - /* - * Get the timestamp verifier out of the - * authenticator and verifier strings. - */ - kin.t1 = kverf.t1; - kin.t2 = kverf.t2; - kin.w2 = kverf.w2; - bzero((caddr_t)kivec, sizeof (kivec)); - bcopy((caddr_t)kauth.session, - (caddr_t)nsd.nsd_key,sizeof(kauth.session)); - - /* - * Decrypt the timestamp verifier in CBC mode. - */ - XXX - - /* - * Validate the timestamp verifier, to - * check that the session key is ok. - */ - nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); - nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); - nsd.nsd_ttl = ntohl(kout.w1); - if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) - nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; - } -#endif /* NFSKERB */ - } - exit(0); + + start_server(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); + signal(SIGUSR1, cleanup); + FD_ZERO(&v4bits); + FD_ZERO(&v6bits); + FD_ZERO(&sockbits); + + 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"); + nfsd_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]); + nfsd_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"); + nfsd_exit(1); + } + 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)); + nfsd_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); } - 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"); + nfsd_exit(1); + } + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + &on, sizeof on) < 0) { + syslog(LOG_ERR, + "can't set v6-only binding for " + "udp6 socket: %m"); + nfsd_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]); + nfsd_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"); + nfsd_exit(1); + } + 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)); + nfsd_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"); + nfsd_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]); + nfsd_exit(1); + } + if (listen(tcpsock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + nfsd_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)); + nfsd_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"); + nfsd_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_V6ONLY, &on, sizeof on) < 0) { + syslog(LOG_ERR, + "can't set v6-only binding for tcp6 " + "socket: %m"); + nfsd_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]); + nfsd_exit(1); + } + if (listen(tcp6sock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + nfsd_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)); + nfsd_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"); + nfsd_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"); + nfsd_exit(1); + } setproctitle("master"); + /* + * We always want a master to have a clean way to to shut nfsd down + * (with unregistration): if the master is killed, it unregisters and + * kills all children. If we run for UDP only (and so do not have to + * loop waiting waiting for accept), we instead make the parent + * a "server" too. start_server will not return. + */ + if (!tcpflag) + start_server(1); /* * Loop forever accepting connections and passing the sockets @@ -551,85 +652,106 @@ main(int argc, char **argv) if (select(maxsock + 1, &ready, NULL, NULL, NULL) < 1) { syslog(LOG_ERR, "select failed: %m"); - 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); - 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 (errno == EINTR) + continue; + nfsd_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); - 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"); + if (errno == ECONNABORTED || + errno == EINTR) + continue; + nfsd_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 = len; + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + 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"); + if (errno == ECONNABORTED || + errno == EINTR) + continue; + nfsd_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 = len; + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + 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); - 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); } - bcopy(he->h_addr, &ia->sin_addr, he->h_length); + 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); + } + break; + default: + break; } } + + ecode = getaddrinfo(hostptr, "nfs", &hints, ai); + if (ecode != 0) { + syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, + gai_strerror(ecode)); + return (1); + } + return (0); } void @@ -648,6 +770,74 @@ nonfs(int signo __unused) void reapchild(int signo __unused) { + pid_t pid; + int i; + + while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) { + for (i = 0; i < nfsdcnt; i++) + if (pid == children[i]) + children[i] = -1; + } +} + +void +unregistration(void) +{ + if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || + (!rpcb_unset(RPCPROG_NFS, 3, NULL))) + syslog(LOG_ERR, "rpcb_unset failed"); +} + +void +killchildren(void) +{ + int i; - while (wait3(NULL, WNOHANG, NULL) > 0); + for (i = 0; i < nfsdcnt; i++) { + if (children[i] > 0) + kill(children[i], SIGKILL); + } +} + +/* + * Cleanup master after SIGUSR1. + */ +void +cleanup(__unused int signo) +{ + nfsd_exit(0); +} + +/* + * Cleanup child after SIGUSR1. + */ +void +child_cleanup(__unused int signo) +{ + exit(0); +} + +void +nfsd_exit(int status) +{ + killchildren(); + unregistration(); + exit(status); +} + +void +start_server(int master) +{ + int status; + + status = 0; + nsd.nsd_nfsd = NULL; + if (nfssvc(NFSSVC_NFSD, &nsd) < 0) { + syslog(LOG_ERR, "nfssvc: %m"); + status = 1; + } + if (master) + nfsd_exit(status); + else + exit(status); } diff --git a/sbin/umount/Makefile b/sbin/umount/Makefile index ae4e3312e9..68c86c0fcc 100644 --- a/sbin/umount/Makefile +++ b/sbin/umount/Makefile @@ -6,7 +6,7 @@ PROG= umount SRCS= umount.c vfslist.c mounttab.c MAN= umount.8 -WARNS?= 2 +WARNS?= 0 MOUNT= ${.CURDIR}/../mount UMNTALL= ${.CURDIR}/../../usr.sbin/rpc.umntall diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c index 68adb66dff..a1d83c8891 100644 --- a/sbin/umount/umount.c +++ b/sbin/umount/umount.c @@ -32,12 +32,13 @@ * * @(#) Copyright (c) 1980, 1989, 1993 The Regents of the University of California. All rights reserved. * @(#)umount.c 8.8 (Berkeley) 5/8/95 - * $FreeBSD: src/sbin/umount/umount.c,v 1.22.2.1 2001/12/13 01:27:15 iedowse Exp $ + * $FreeBSD: src/sbin/umount/umount.c,v 1.28 2001/10/13 02:04:54 iedowse Exp $ * $DragonFly: src/sbin/umount/umount.c,v 1.4 2005/11/06 12:51:01 swildner Exp $ */ #include #include +#include #include #include @@ -58,6 +59,7 @@ typedef enum { MNTON, MNTFROM, NOTHING } mntwhat; typedef enum { MARK, UNMARK, NAME, COUNT, FREE } dowhat; +struct addrinfo *nfshost_ai = NULL; int fflag, vflag; char *nfshost; @@ -68,19 +70,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(); @@ -123,6 +128,13 @@ 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) + errx(1, "%s: %s", nfshost, gai_strerror(error)); + } + switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) @@ -155,7 +167,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; } @@ -168,7 +180,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; } @@ -203,11 +215,9 @@ umountall(char **typelist) strcmp(fs->fs_type, FSTAB_RO) && strcmp(fs->fs_type, FSTAB_RQ)) continue; - /* If an unknown file system type, complain. */ - if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) { - warnx("%s: unknown mount type", fs->fs_vfstype); + /* Ignore unknown file system types. */ + if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) continue; - } if (checkvfsname(fs->fs_vfstype, typelist)) continue; @@ -220,33 +230,29 @@ umountall(char **typelist) err(1, "malloc failed"); 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. @@ -315,14 +321,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) { 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); } } } @@ -333,21 +354,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. @@ -375,19 +381,58 @@ umountfs(char *name, char **typelist) return (1); } free(mntfromnamerev); - /* - * Check if we have to start the rpc-call later. - * If there are still identical nfs-names mounted, - * we skip the rpc-call. Obviously this has to - * happen before unmount(2), but it should happen - * after the previous namecheck. - */ - if (strcmp(type, "nfs") == 0 && getmntname(mntfromname, NULL, NOTHING, - &type, COUNT) != NULL) - do_rpc = 1; - else - do_rpc = 0; - if (!namematch(hp)) + return (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 addrinfo *ai, hints; + int do_rpc; + CLIENT *clp; + char *nfsdirname, *orignfsdirname; + char *hostp, *delimp; + + ai = NULL; + do_rpc = 0; + hostp = NULL; + nfsdirname = delimp = orignfsdirname = NULL; + memset(&hints, 0, sizeof hints); + + if (strcmp(type, "nfs") == 0) { + 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, + * we skip the rpc-call. Obviously this has to + * happen before unmount(2), but it should happen + * after the previous namecheck. + * A non-NULL return means that this is the last + * mount from mntfromname that is still mounted. + */ + if (getmntname(mntfromname, NULL, NOTHING, &type, COUNT) + != NULL) + do_rpc = 1; + } + + if (!namematch(ai)) return (1); if (unmount(mntonname, fflag) != 0 ) { warn("unmount of %s failed", mntonname); @@ -399,27 +444,21 @@ 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) { - clnt_pcreateerror("Cannot MNT PRC"); + if (ai != NULL && !(fflag & MNT_FORCE) && do_rpc) { + clp = clnt_create(hostp, RPCPROG_MNT, RPCMNT_VER1, "udp"); + if (clp == NULL) { + warnx("%s: %s", hostp, + clnt_spcreateerror("RPCPROG_MNT")); 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, nfsdirname, xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) { - clnt_perror(clp, "Bad MNT RPC"); + warnx("%s: %s", hostp, + clnt_sperror(clp, "RPCMNT_UMOUNT")); return (1); } /* @@ -545,30 +584,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/conf/files b/sys/conf/files index ea8cc475bb..053b72efe5 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -817,13 +817,13 @@ netproto/atm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netproto/atm/spans/spans_xdr.x" \ - compile-with "rpcgen -h -C $S/netproto/atm/spans/spans_xdr.x > spans_xdr.h" \ + compile-with "rpcgen -h -C $S/netproto/atm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netproto/atm/spans/spans_xdr.x" \ - compile-with "rpcgen -c -C $S/netproto/atm/spans/spans_xdr.x > spans_xdr.c" \ + compile-with "rpcgen -c -C $S/netproto/atm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ diff --git a/sys/netproto/atm/spans/spans_kxdr.c b/sys/netproto/atm/spans/spans_kxdr.c index 7f38ce42e4..7d1e35ecbc 100644 --- a/sys/netproto/atm/spans/spans_kxdr.c +++ b/sys/netproto/atm/spans/spans_kxdr.c @@ -86,8 +86,7 @@ * xdr. */ -#include -#include +#include /* * constants specific to the xdr "protocol" diff --git a/include/rpc/xdr.h b/sys/netproto/atm/spans/spans_kxdr.h similarity index 57% copy from include/rpc/xdr.h copy to sys/netproto/atm/spans/spans_kxdr.h index 1e1ca7e353..3756f8f5c9 100644 --- a/include/rpc/xdr.h +++ b/sys/netproto/atm/spans/spans_kxdr.h @@ -1,4 +1,7 @@ -/* +/* $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ */ +/* $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 * media and as a part of the software program in whole or part. Users @@ -7,9 +10,6 @@ * 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. @@ -26,22 +26,49 @@ * 2550 Garcia Avenue * Mountain View, California 94043 * + * from: @(#)types.h 1.18 87/07/24 SMI + * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC * from: @(#)xdr.h 1.19 87/04/22 SMI * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC - * $FreeBSD: src/include/rpc/xdr.h,v 1.14.2.1 2003/03/20 12:59:55 jedgar Exp $ - * $DragonFly: src/include/rpc/xdr.h,v 1.3 2003/11/14 01:01:50 dillon Exp $ + * $FreeBSD: src/sys/netatm/spans/spans_kxdr.h,v 1.3 2005/01/07 01:45:38 imp Exp $ */ +#ifndef _SPANS_KXDR_H +#define _SPANS_KXDR_H + +/* + * Rpc additions to + */ +#include + +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 +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#ifndef NULL +# define NULL 0 +#endif + /* * xdr.h, External Data Representation Serialization Routines. * * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef _RPC_XDR_H -#define _RPC_XDR_H -#include - /* * XDR provides a conventional way for converting between C data * types and an external bit-string representation. Library supplied @@ -98,28 +125,29 @@ 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) (struct __rpc_xdr *, long *); - /* put a long to underlying stream */ - bool_t (*x_putlong) (struct __rpc_xdr *, long *); - /* get some bytes from underlying stream */ - bool_t (*x_getbytes) (struct __rpc_xdr *, caddr_t, u_int); - /* put some bytes to underlying stream */ - bool_t (*x_putbytes) (struct __rpc_xdr *, caddr_t, u_int); + bool_t (*x_getlong)(struct __rpc_xdr *, long *); + /* put a long to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, const long *); + /* get some bytes from " */ + bool_t (*x_getbytes)(struct __rpc_xdr *, char *, u_int); + /* put some bytes to " */ + bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, u_int); /* returns bytes off from beginning */ - u_int (*x_getpostn) (struct __rpc_xdr *); + u_int (*x_getpostn)(struct __rpc_xdr *); /* lets you reposition the stream */ - bool_t (*x_setpostn) (struct __rpc_xdr *, u_int); + bool_t (*x_setpostn)(struct __rpc_xdr *, u_int); /* buf quick ptr to buffered data */ - int32_t *(*x_inline) (struct __rpc_xdr *, u_int); + int32_t *(*x_inline)(struct __rpc_xdr *, u_int); /* free privates of this xdr_stream */ - void (*x_destroy) (struct __rpc_xdr *); + void (*x_destroy)(struct __rpc_xdr *); + bool_t (*x_control)(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 */ - u_int x_handy; /* extra private word */ + 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; /* @@ -130,21 +158,14 @@ typedef struct __rpc_xdr { * 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) (XDR *, void *, u_int); -#else -/* - * XXX can't actually prototype it, because some take two args!!! - */ -typedef bool_t (*xdrproc_t) (/* XDR *, void *, u_int */); -#endif +typedef bool_t (*xdrproc_t)(XDR *, void *, u_int); /* * Operations defined on a XDR handle * * XDR *xdrs; * long *longp; - * caddr_t addr; + * char * addr; * u_int len; * u_int pos; */ @@ -158,6 +179,29 @@ typedef bool_t (*xdrproc_t) (/* 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) \ @@ -190,10 +234,25 @@ typedef bool_t (*xdrproc_t) (/* 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 - * a entry with a null procedure pointer. The xdr_union routine gets + * an entry with a null procedure pointer. The xdr_union routine gets * the discriminant value and then searches the array of structures * for a matching value. If a match is found the associated xdr routine * is called to handle that part of the union. If there is @@ -221,8 +280,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)) @@ -230,46 +294,50 @@ 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. */ __BEGIN_DECLS -extern bool_t xdr_void (void); -extern bool_t xdr_int (XDR *, int *); -extern bool_t xdr_u_int (XDR *, u_int *); -extern bool_t xdr_long (XDR *, long *); -extern bool_t xdr_u_long (XDR *, u_long *); -extern bool_t xdr_short (XDR *, short *); -extern bool_t xdr_u_short (XDR *, u_short *); -extern bool_t xdr_int16_t (XDR *, int16_t *); -extern bool_t xdr_u_int16_t (XDR *, u_int16_t *); -extern bool_t xdr_int32_t (XDR *, int32_t *); -extern bool_t xdr_u_int32_t (XDR *, u_int32_t *); -extern bool_t xdr_int64_t (XDR *, int64_t *); -extern bool_t xdr_u_int64_t (XDR *, u_int64_t *); -extern bool_t xdr_bool (XDR *, bool_t *); -extern bool_t xdr_enum (XDR *, enum_t *); -extern bool_t xdr_array (XDR *, char **, u_int *, u_int, u_int, xdrproc_t); -extern bool_t xdr_bytes (XDR *, char **, u_int *, u_int); -extern bool_t xdr_opaque (XDR *, caddr_t, u_int); -extern bool_t xdr_string (XDR *, char **, u_int); -extern bool_t xdr_union (XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t); -extern unsigned long xdr_sizeof (xdrproc_t, void *); -extern bool_t xdr_char (XDR *, char *); -extern bool_t xdr_u_char (XDR *, u_char *); -extern bool_t xdr_vector (XDR *, char *, u_int, u_int, xdrproc_t); -extern bool_t xdr_float (XDR *, float *); -extern bool_t xdr_double (XDR *, double *); -extern bool_t xdr_reference (XDR *, caddr_t *, u_int, xdrproc_t); -extern bool_t xdr_pointer (XDR *, caddr_t *, u_int, xdrproc_t); -extern bool_t xdr_wrapstring (XDR *, char **); -extern void xdr_free (xdrproc_t, char *); +extern bool_t xdr_void(void); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, u_int *); +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, u_long *); +extern bool_t xdr_short(XDR *, short *); +extern bool_t xdr_u_short(XDR *, u_short *); +extern bool_t xdr_int16_t(XDR *, int16_t *); +extern bool_t xdr_u_int16_t(XDR *, u_int16_t *); +extern bool_t xdr_int32_t(XDR *, int32_t *); +extern bool_t xdr_u_int32_t(XDR *, u_int32_t *); +extern bool_t xdr_int64_t(XDR *, int64_t *); +extern bool_t xdr_u_int64_t(XDR *, u_int64_t *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int); +extern bool_t xdr_opaque(XDR *, char *, u_int); +extern bool_t xdr_string(XDR *, char **, u_int); +extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, u_char *); +extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_quadruple(XDR *, long double *); +extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); +extern void xdr_free(xdrproc_t, void *); +extern bool_t xdr_hyper(XDR *, quad_t *); +extern bool_t xdr_u_hyper(XDR *, u_quad_t *); +extern bool_t xdr_longlong_t(XDR *, quad_t *); +extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *); __END_DECLS /* @@ -282,7 +350,7 @@ struct netobj { char *n_bytes; }; typedef struct netobj netobj; -extern bool_t xdr_netobj (XDR *, struct netobj *); +extern bool_t xdr_netobj(XDR *, struct netobj *); /* * These are the public routines for the various implementations of @@ -290,26 +358,22 @@ extern bool_t xdr_netobj (XDR *, struct netobj *); */ __BEGIN_DECLS /* XDR using memory buffers */ -extern void xdrmem_create (XDR *, char *, u_int, enum xdr_op); - -#ifdef _STDIO_H_ -/* XDR using stdio library */ -extern void xdrstdio_create (XDR *, FILE *, enum xdr_op); -#endif +extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op); /* XDR pseudo records for tcp */ -extern void xdrrec_create (XDR *, u_int, u_int, char *, - int (*) (caddr_t, caddr_t, int), - int (*) (caddr_t, caddr_t, int)); +extern void xdrrec_create(XDR *, u_int, u_int, void *, + int (*)(void *, void *, int), + int (*)(void *, void *, int)); /* make end of xdr record */ -extern bool_t xdrrec_endofrecord (XDR *, int); +extern bool_t xdrrec_endofrecord(XDR *, int); /* move to beginning of next record */ -extern bool_t xdrrec_skiprecord (XDR *); +extern bool_t xdrrec_skiprecord(XDR *); /* true if no more input */ -extern bool_t xdrrec_eof (XDR *); +extern bool_t xdrrec_eof(XDR *); +extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int); __END_DECLS -#endif /* !_RPC_XDR_H */ +#endif /* !_SPANS_KXDR_H */ diff --git a/sys/netproto/atm/spans/spans_msg.c b/sys/netproto/atm/spans/spans_msg.c index 3f2c144ccd..1f89935375 100644 --- a/sys/netproto/atm/spans/spans_msg.c +++ b/sys/netproto/atm/spans/spans_msg.c @@ -37,7 +37,6 @@ #include -#include #include "spans_xdr.h" #include "spans_var.h" diff --git a/sys/netproto/atm/spans/spans_xdr.x b/sys/netproto/atm/spans/spans_xdr.x index 1e167afc1b..13cb9a1244 100644 --- a/sys/netproto/atm/spans/spans_xdr.x +++ b/sys/netproto/atm/spans/spans_xdr.x @@ -1,4 +1,4 @@ -%/* +%/*- % * % * =================================== % * HARP | Host ATM Research Platform @@ -23,7 +23,7 @@ % * Copies of this Software may be made, however, the above copyright % * notice must be reproduced on all copies. % * -% * @(#) $FreeBSD: src/sys/netatm/spans/spans_xdr.x,v 1.3 1999/11/18 08:18:13 peter Exp $ +% * @(#) $FreeBSD: src/sys/netatm/spans/spans_xdr.x,v 1.5 2005/01/07 01:45:38 imp Exp $ % * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_xdr.x,v 1.2 2003/06/17 04:28:49 dillon Exp $ % * % */ @@ -48,7 +48,7 @@ %#ifndef _SPANS_SPANS_XDR_H %#define _SPANS_SPANS_XDR_H % -%#include +%#include % #endif @@ -62,7 +62,7 @@ % */ % %#ifndef lint -%static const char RCSid[] = "@(#) $FreeBSD: src/sys/netatm/spans/spans_xdr.x,v 1.3 1999/11/18 08:18:13 peter Exp $"; +%static const char RCSid[] = "@(#) $FreeBSD: src/sys/netatm/spans/spans_xdr.x,v 1.5 2005/01/07 01:45:38 imp Exp $"; %#endif % #endif diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile index e53047fc32..900d15096b 100644 --- a/usr.bin/chpass/Makefile +++ b/usr.bin/chpass/Makefile @@ -8,7 +8,7 @@ SRCS= chpass.c edit.c field.c pw_copy.c pw_scan.c pw_util.c pw_yp.c \ GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c yppasswd_private.h \ yppasswd_private_clnt.c yppasswd_private_xdr.c BINMODE=4555 -WARNS?= 1 +WARNS?= 0 .PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../usr.sbin/vipw \ ${.CURDIR}/../../libexec/ypxfr \ ${.CURDIR}/../../usr.sbin/rpc.yppasswdd \ diff --git a/usr.bin/keylogin/keylogin.c b/usr.bin/keylogin/keylogin.c index 1322190621..f2a24a67e2 100644 --- a/usr.bin/keylogin/keylogin.c +++ b/usr.bin/keylogin/keylogin.c @@ -29,6 +29,7 @@ * * @(#)keylogin.c 1.4 91/03/11 Copyr 1986 Sun Micro * + * $FreeBSD: src/usr.bin/keylogin/keylogin.c,v 1.4 2002/06/30 05:25:01 obrien Exp $ * $DragonFly: src/usr.bin/keylogin/keylogin.c,v 1.4 2007/11/25 01:28:23 swildner Exp $ */ @@ -51,7 +52,7 @@ int main(void) { 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/passwd/Makefile b/usr.bin/passwd/Makefile index 7b94f9309e..21b8059a24 100644 --- a/usr.bin/passwd/Makefile +++ b/usr.bin/passwd/Makefile @@ -80,7 +80,7 @@ yppasswd_private_clnt.c: ${RPCSRC_PRIV} BINMODE=4555 LINKS=${BINDIR}/passwd ${BINDIR}/yppasswd MLINKS=passwd.1 yppasswd.1 -WARNS?= 1 +WARNS?= 0 beforeinstall: .for i in passwd yppasswd diff --git a/usr.bin/rpcgen/rpc_clntout.c b/usr.bin/rpcgen/rpc_clntout.c index a5748c48a8..d1edab2258 100644 --- a/usr.bin/rpcgen/rpc_clntout.c +++ b/usr.bin/rpcgen/rpc_clntout.c @@ -5,33 +5,32 @@ * 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 * - * @(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI + * @(#)rpc_clntout.c 1.15 94/04/25 SMI; 1.11 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_clntout.c,v 1.12 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_clntout.c,v 1.5 2004/06/19 16:40:36 joerg Exp $ */ -#ident "@(#)rpc_clntout.c 1.15 94/04/25 SMI" - /* * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler * Copyright (C) 1987, Sun Microsytsems, Inc. @@ -40,10 +39,9 @@ #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" -extern void pdeclaration(char *, declaration *, int, char *); -void printarglist(proc_list *, char *, char *, char *); static void write_program(definition *); static void printbody(proc_list *); @@ -105,102 +103,52 @@ write_program(definition *def) /* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ void -printarglist(proc_list *proc, char *result, char *addargname, char *addargtype) +printarglist(proc_list *proc, const char *result, const char *addargname, + const char *addargtype) { decl_list *l; if (!newstyle) { /* old style: always pass argument by reference */ - if (Cflag) { /* C++ style heading */ - f_print(fout, "("); - ptype(proc->args.decls->decl.prefix, - proc->args.decls->decl.type, 1); + f_print(fout, "("); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); - if (mtflag) {/* Generate result field */ - f_print(fout, "*argp, "); - ptype(proc->res_prefix, proc->res_type, 1); - f_print(fout, "*%s, %s%s)\n", - result, addargtype, addargname); - } else - f_print(fout, "*argp, %s%s)\n", addargtype, - addargname); - } else { - if (!mtflag) - f_print(fout, "(argp, %s)\n", addargname); - else - f_print(fout, "(argp, %s, %s)\n", - result, addargname); - f_print(fout, "\t"); - ptype(proc->args.decls->decl.prefix, - proc->args.decls->decl.type, 1); - f_print(fout, "*argp;\n"); - if (mtflag) { - f_print(fout, "\t"); - ptype(proc->res_prefix, proc->res_type, 1); - f_print(fout, "*%s;\n", result); - } - } + if (mtflag) {/* Generate result field */ + f_print(fout, "*argp, "); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, %s%s)\n", + result, addargtype, addargname); + } else + f_print(fout, "*argp, %s%s)\n", addargtype, addargname); } else if (streq(proc->args.decls->decl.type, "void")) { /* newstyle, 0 argument */ if (mtflag) { f_print(fout, "("); - - if (Cflag) { - ptype(proc->res_prefix, proc->res_type, 1); - f_print(fout, "*%s, %s%s)\n", - result, addargtype, addargname); - } - else { - f_print(fout, "(%s)\n", addargname); - } - } else if (Cflag) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, %s%s)\n", + result, addargtype, addargname); + } else f_print(fout, "(%s%s)\n", addargtype, addargname); - } else { - f_print(fout, "(%s)\n", addargname); - } } else { /* new style, 1 or multiple arguments */ - if (!Cflag) { - f_print(fout, "("); - for (l = proc->args.decls; l != NULL; l = l->next) - f_print(fout, "%s, ", l->decl.name); - if (mtflag) - f_print(fout, "%s, ", result); - - f_print(fout, "%s)\n", addargname); - for (l = proc->args.decls; l != NULL; l = l->next) { - pdeclaration(proc->args.argname, - &l->decl, 1, ";\n"); - } - if (mtflag) { - f_print(fout, "\t"); - ptype(proc->res_prefix, proc->res_type, 1); - f_print(fout, "*%s;\n", result); - } - - } else { /* C++ style header */ - f_print(fout, "("); - for (l = proc->args.decls; l != NULL; l = l->next) { - pdeclaration(proc->args.argname, &l->decl, 0, - ", "); - } - if (mtflag) { - ptype(proc->res_prefix, proc->res_type, 1); - f_print(fout, "*%s, ", result); + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 0, ", "); + } + if (mtflag) { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*%s, ", result); - } - f_print(fout, "%s%s)\n", addargtype, addargname); } + f_print(fout, "%s%s)\n", addargtype, addargname); } - - if (!Cflag) - f_print(fout, "\t%s%s;\n", addargtype, addargname); } -static char * -ampr(char *type) +static const char * +ampr(const char *type) { if (isvectordef(type, REL_ALIAS)) return (""); @@ -245,7 +193,7 @@ printbody(proc_list *proc) f_print(fout, "\t if "); f_print(fout, - "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ", + "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ", proc->proc_name); f_print(fout, "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, " "(caddr_t) %s%s,", stringfix(proc->res_type), diff --git a/usr.bin/rpcgen/rpc_cout.c b/usr.bin/rpcgen/rpc_cout.c index eac1105272..4f0be04ec0 100644 --- a/usr.bin/rpcgen/rpc_cout.c +++ b/usr.bin/rpcgen/rpc_cout.c @@ -5,43 +5,41 @@ * 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 * - * @(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI - * $FreeBSD: src/usr.bin/rpcgen/rpc_cout.c,v 1.7 1999/08/28 01:05:16 peter Exp $ + * @(#)rpc_cout.c 1.14 93/07/05 SMI; 1.13 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_cout.c,v 1.17 2007/11/20 01:46:12 jb Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_cout.c,v 1.5 2008/10/16 01:52:33 swildner Exp $ */ -#ident "@(#)rpc_cout.c 1.14 93/07/05 SMI" - /* * rpc_cout.c, XDR routine outputter for the RPC protocol compiler * Copyright (C) 1987, Sun Microsystems, Inc. */ -#include #include #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" static void print_header(definition *); @@ -54,7 +52,7 @@ static void emit_struct(definition *); static void emit_typedef(definition *); static void emit_inline(int, declaration *, int); static void emit_single_in_line(int, declaration *, int, relation); -static char *upcase(char *str); +static char *upcase(const char *); /* * Emit the C-routine for the given definition @@ -93,14 +91,14 @@ emit(definition *def) emit_typedef(def); break; /* DEF_CONST and DEF_PROGRAM have already been handled */ - default: + default: break; } print_trailer(); } static int -findtype(definition *def, char *type) +findtype(definition *def, const char *type) { if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) @@ -110,7 +108,7 @@ findtype(definition *def, char *type) } static int -undefined(char *type) +undefined(const char *type) { definition *def; @@ -120,25 +118,16 @@ undefined(char *type) static void -print_generic_header(char *procname, int pointerp) +print_generic_header(const char *procname, int pointerp) { f_print(fout, "\n"); f_print(fout, "bool_t\n"); - if (Cflag) { - f_print(fout, "xdr_%s(", procname); - f_print(fout, "XDR *xdrs, "); - f_print(fout, "%s ", procname); - if (pointerp) - f_print(fout, "*"); - f_print(fout, "objp)\n{\n\n"); - } else { - f_print(fout, "xdr_%s(xdrs, objp)\n", procname); - f_print(fout, "\tXDR *xdrs;\n"); - f_print(fout, "\t%s ", procname); - if (pointerp) - f_print(fout, "*"); - f_print(fout, "objp;\n{\n\n"); - } + f_print(fout, "xdr_%s(", procname); + f_print(fout, "XDR *xdrs, "); + f_print(fout, "%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp)\n{\n\n"); } static void @@ -149,7 +138,7 @@ print_header(definition *def) def->def.ty.rel)); /* Now add Inline support */ - if (rpcgen_inline == 0) + if (inline_size == 0) return; /* May cause lint to complain. but ... */ f_print(fout, "\tlong *buf;\n\n"); @@ -170,20 +159,20 @@ print_trailer(void) static void -print_ifopen(int indent, char *name) +print_ifopen(int indent, const char *name) { tabify(fout, indent); f_print(fout, "if (!xdr_%s(xdrs", name); } static void -print_ifarg(char *arg) +print_ifarg(const char *arg) { f_print(fout, ", %s", arg); } static void -print_ifsizeof(int indent, char *prefix, char *type) +print_ifsizeof(int indent, const char *prefix, const char *type) { if (indent) { f_print(fout, ",\n"); @@ -202,24 +191,30 @@ print_ifsizeof(int indent, char *prefix, char *type) } static void -print_ifclose(int indent) +print_ifclose(int indent, int brace) { f_print(fout, "))\n"); tabify(fout, indent); f_print(fout, "\treturn (FALSE);\n"); + if (brace) + f_print(fout, "\t}\n"); } static void -print_ifstat(int indent, char *prefix, char *type, relation rel, char *amax, - char *objname, char *name) +print_ifstat(int indent, const char *prefix, const char *type, relation rel, + const char *amax, const char *objname, const char *name) { - char *alt = NULL; + const char *alt = NULL; + int brace = 0; switch (rel) { case REL_POINTER: + brace = 1; + f_print(fout, "\t{\n"); + f_print(fout, "\t%s **pp = %s;\n", type, objname); print_ifopen(indent, "pointer"); print_ifarg("(char **)"); - f_print(fout, "%s", objname); + f_print(fout, "pp"); print_ifsizeof(0, prefix, type); break; case REL_VECTOR: @@ -273,16 +268,16 @@ print_ifstat(int indent, char *prefix, char *type, relation rel, char *amax, print_ifarg(objname); break; } - print_ifclose(indent); + print_ifclose(indent, brace); } /* ARGSUSED */ static void -emit_enum(definition *def) +emit_enum(definition *def __unused) { print_ifopen(1, "enum"); print_ifarg("(enum_t *)objp"); - print_ifclose(1); + print_ifclose(1, 0); } static void @@ -312,8 +307,8 @@ emit_union(definition *def) case_list *cl; declaration *cs; char *object; - char *vecformat = "objp->%s_u.%s"; - char *format = "&objp->%s_u.%s"; + const char *vecformat = "objp->%s_u.%s"; + const char *format = "&objp->%s_u.%s"; print_stat(1, &def->def.un.enum_decl); f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); @@ -324,8 +319,8 @@ emit_union(definition *def) continue; cs = &cl->case_decl; if (!streq(cs->type, "void")) { - object = alloc(strlen(def->def_name) + strlen(format) + - strlen(cs->name) + 1); + object = xmalloc(strlen(def->def_name) + + strlen(format) + strlen(cs->name) + 1); if (isvectordef (cs->type, cs->rel)) { s_print(object, vecformat, def->def_name, cs->name); @@ -343,8 +338,8 @@ emit_union(definition *def) if (dflt != NULL) { if (!streq(dflt->type, "void")) { f_print(fout, "\tdefault:\n"); - object = alloc(strlen(def->def_name) + strlen(format) + - strlen(dflt->name) + 1); + object = xmalloc(strlen(def->def_name) + + strlen(format) + strlen(dflt->name) + 1); if (isvectordef (dflt->type, dflt->rel)) { s_print(object, vecformat, def->def_name, dflt->name); @@ -376,10 +371,12 @@ inline_struct(definition *def, int flag) int i, size; decl_list *cur, *psav; bas_type *ptr; - char *sizestr, *plus; + char *sizestr; + const char *plus; char ptemp[256]; int indent = 1; + cur = NULL; if (flag == PUT) f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); else @@ -418,27 +415,23 @@ inline_struct(definition *def, int flag) /* now concatenate to sizestr !!!! */ if (sizestr == NULL) { - sizestr = strdup(ptemp); + sizestr = xstrdup(ptemp); } else { - sizestr = realloc(sizestr, + sizestr = xrealloc(sizestr, strlen(sizestr) +strlen(ptemp)+1); - if (sizestr == NULL){ - warnx("fatal error: no memory"); - crash(); - }; sizestr = strcat(sizestr, ptemp); /* build up length of array */ } } } else { if (i > 0) { - if (sizestr == NULL && size < rpcgen_inline){ + if (sizestr == NULL && size < inline_size) { /* * don't expand into inline code - * if size < rpcgen_inline + * if size < inline_size */ - while (cur != dl){ + while (cur != dl) { print_stat(indent + 1, &cur->decl); cur = cur->next; @@ -490,9 +483,9 @@ inline_struct(definition *def, int flag) } } - if (i > 0) - if (sizestr == NULL && size < rpcgen_inline) { - /* don't expand into inline code if size < rpcgen_inline */ + if (i > 0) { + if (sizestr == NULL && size < inline_size) { + /* don't expand into inline code if size < inline_size */ while (cur != dl) { print_stat(indent + 1, &cur->decl); cur = cur->next; @@ -528,6 +521,7 @@ inline_struct(definition *def, int flag) } f_print(fout, "\t\t}\n"); } + } } static void @@ -538,7 +532,7 @@ emit_struct(definition *def) bas_type *ptr; int can_inline; - if (rpcgen_inline == 0) { + if (inline_size == 0) { /* No xdr_inlining at all */ for (dl = def->def.st.decls; dl != NULL; dl = dl->next) print_stat(1, &dl->decl); @@ -569,14 +563,14 @@ emit_struct(definition *def) break; /* can be inlined */ } } else { - if (size >= rpcgen_inline) { + if (size >= inline_size) { can_inline = 1; break; /* can be inlined */ } size = 0; } } - if (size >= rpcgen_inline) + if (size >= inline_size) can_inline = 1; if (can_inline == 0) { /* can not inline, drop back to old mode */ @@ -604,9 +598,9 @@ emit_struct(definition *def) static void emit_typedef(definition *def) { - char *prefix = def->def.ty.old_prefix; - char *type = def->def.ty.old_type; - char *amax = def->def.ty.array_max; + const char *prefix = def->def.ty.old_prefix; + const char *type = def->def.ty.old_type; + const char *amax = def->def.ty.array_max; relation rel = def->def.ty.rel; print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); @@ -615,9 +609,9 @@ emit_typedef(definition *def) static void print_stat(int indent, declaration *dec) { - char *prefix = dec->prefix; - char *type = dec->type; - char *amax = dec->array_max; + const char *prefix = dec->prefix; + const char *type = dec->type; + const char *amax = dec->array_max; relation rel = dec->rel; char name[256]; @@ -629,7 +623,6 @@ print_stat(int indent, declaration *dec) } - static void emit_inline(int indent, declaration *decl, int flag) { @@ -651,6 +644,7 @@ emit_inline(int indent, declaration *decl, int flag) f_print(fout, "}\n"); tabify(fout, indent); f_print(fout, "}\n"); + break; default: break; } @@ -660,7 +654,6 @@ static void emit_single_in_line(int indent, declaration *decl, int flag, relation rel) { char *upp_case; - int freed = 0; tabify(fout, indent); if (flag == PUT) @@ -676,15 +669,13 @@ emit_single_in_line(int indent, declaration *decl, int flag, relation rel) if (strcmp(upp_case, "INT") == 0) { free(upp_case); - freed = 1; - upp_case = "LONG"; + upp_case = strdup("LONG"); } if (strcmp(upp_case, "U_INT") == 0) { free(upp_case); - freed = 1; - upp_case = "U_LONG"; + upp_case = strdup("U_LONG"); } if (flag == PUT) { if (rel == REL_ALIAS) @@ -695,18 +686,15 @@ emit_single_in_line(int indent, declaration *decl, int flag, relation rel) } else { f_print(fout, "%s(buf);\n", upp_case); } - if (!freed) - free(upp_case); + free(upp_case); } static char * -upcase(char *str) +upcase(const char *str) { char *ptr, *hptr; - ptr = malloc(strlen(str)+1); - if (ptr == NULL) - errx(1, "malloc failed"); + ptr = xmalloc(strlen(str)+1); hptr = ptr; while (*str != '\0') diff --git a/usr.bin/rpcgen/rpc_hout.c b/usr.bin/rpcgen/rpc_hout.c index e48e6de50c..94d74e3871 100644 --- a/usr.bin/rpcgen/rpc_hout.c +++ b/usr.bin/rpcgen/rpc_hout.c @@ -5,33 +5,32 @@ * 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 * - * @(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI + * @(#)rpc_hout.c 1.16 94/04/25 SMI; 1.12 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_hout.c,v 1.15 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_hout.c,v 1.5 2004/06/19 16:40:36 joerg Exp $ */ -#ident "@(#)rpc_hout.c 1.16 94/04/25 SMI" - /* * rpc_hout.c, Header file outputter for the RPC protocol compiler * Copyright (C) 1987, Sun Microsystems, Inc. @@ -39,30 +38,28 @@ #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" -void storexdrfuncdecl(char *, int); +void storexdrfuncdecl(const char *, int); static void pconstdef(definition *); static void pstructdef(definition *); static void puniondef(definition *); -static void pprogramdef(definition *); -static void pstructdef(definition *); +static void pprogramdef(definition *, int); static void penumdef(definition *); static void ptypedef(definition *); -static void pdefine(char *, char *); -static int undefined2(char *, char *); -static void parglist(proc_list *, char *); -static void pprocdef(proc_list *, version_list *, char *, int, int); -void pdeclaration(char *, declaration *, int, char *); - -static char RESULT[] = "clnt_res"; +static void pdefine(const char *, const char *); +static int undefined2(const char *, const char *); +static void parglist(proc_list *, const char *); +static void pprocdef(proc_list *, version_list *, const char *, int); /* * Print the C-version of an xdr definition */ void -print_datadef(definition *def) +print_datadef(definition *def, int headeronly) { + if (def->def_kind == DEF_PROGRAM) /* handle data only */ return; @@ -83,7 +80,7 @@ print_datadef(definition *def) ptypedef(def); break; case DEF_PROGRAM: - pprogramdef(def); + pprogramdef(def, headeronly); break; case DEF_CONST: pconstdef(def); @@ -100,12 +97,12 @@ print_datadef(definition *def) void -print_funcdef(definition *def) +print_funcdef(definition *def, int headeronly) { switch (def->def_kind) { case DEF_PROGRAM: f_print(fout, "\n"); - pprogramdef(def); + pprogramdef(def, headeronly); break; default: break; @@ -116,11 +113,11 @@ print_funcdef(definition *def) out at the end of the file */ void -storexdrfuncdecl(char *name, int pointerp) +storexdrfuncdecl(const char *name, int pointerp) { xdrfunc * xdrptr; - xdrptr = malloc(sizeof(struct xdrfunc)); + xdrptr = XALLOC(struct xdrfunc); xdrptr->name = name; xdrptr->pointerp = pointerp; @@ -135,13 +132,10 @@ storexdrfuncdecl(char *name, int pointerp) } void -print_xdr_func_def(char *name, int pointerp, int i) +print_xdr_func_def(const char *name, int pointerp) { - if (i == 2) - f_print(fout, "extern bool_t xdr_%s();\n", name); - else - f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name, - name, pointerp ? "*" : ""); + f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name, + name, pointerp ? "*" : ""); } @@ -184,7 +178,7 @@ static void pstructdef(definition *def) { decl_list *l; - char *name = def->def_name; + const char *name = def->def_name; f_print(fout, "struct %s {\n", name); for (l = def->def.st.decls; l != NULL; l = l->next) @@ -198,7 +192,7 @@ static void puniondef(definition *def) { case_list *l; - char *name = def->def_name; + const char *name = def->def_name; declaration *decl; f_print(fout, "struct %s {\n", name); @@ -223,13 +217,13 @@ puniondef(definition *def) } static void -pdefine(char *name, char *num) +pdefine(const char *name, const char *num) { f_print(fout, "#define\t%s %s\n", name, num); } static void -puldefine(char *name, char *num) +puldefine(const char *name, const char *num) { f_print(fout, "#define\t%s ((unsigned long)(%s))\n", name, num); } @@ -253,23 +247,28 @@ define_printed(proc_list *stop, version_list *start) } static void -pfreeprocdef(char * name, char *vers, int mode) +pfreeprocdef(const char * name, const char *vers) { f_print(fout, "extern int "); pvname(name, vers); - if (mode == 1) - f_print(fout,"_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n"); - else - f_print(fout,"_freeresult();\n"); + f_print(fout, "_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n"); +} + +static void +pdispatch(const char * name, const char *vers) +{ + + f_print(fout, "void "); + pvname(name, vers); + f_print(fout, "(struct svc_req *rqstp, SVCXPRT *transp);\n"); } static void -pprogramdef(definition *def) +pprogramdef(definition *def, int headeronly) { version_list *vers; proc_list *proc; - int i; - char *ext; + const char *ext; pargdef(def); @@ -284,61 +283,27 @@ pprogramdef(definition *def) } puldefine(vers->vers_name, vers->vers_num); - /* - * Print out 2 definitions, one for ANSI-C, another for - * old K & R C - */ - - if(!Cflag){ - ext = "extern "; - for (proc = vers->procs; proc != NULL; - proc = proc->next) { - if (!define_printed(proc, - def->def.pr.versions)) { - puldefine(proc->proc_name, - proc->proc_num); - } - f_print(fout, "%s", ext); - pprocdef(proc, vers, NULL, 0, 2); - - if (mtflag) { - f_print(fout, "%s", ext); - pprocdef(proc, vers, NULL, 1, 2); - } - } - pfreeprocdef(def->def_name, vers->vers_num, 2); - } else { - for (i = 1; i < 3; i++) { - if (i == 1) { - f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); - ext = "extern "; - } else { - f_print(fout, "\n#else /* K&R C */\n"); - ext = "extern "; - } - - for (proc = vers->procs; proc != NULL; - proc = proc->next) { - if (!define_printed(proc, - def->def.pr.versions)) { - puldefine(proc->proc_name, - proc->proc_num); - } - f_print(fout, "%s", ext); - pprocdef(proc, vers, "CLIENT *", 0, i); - f_print(fout, "%s", ext); - pprocdef(proc, vers, "struct svc_req *", 1, i); - } - pfreeprocdef(def->def_name, vers->vers_num, i); + f_print(fout, "\n"); + ext = "extern "; + if (headeronly) { + f_print(fout, "%s", ext); + pdispatch(def->def_name, vers->vers_num); + } + for (proc = vers->procs; proc != NULL; proc = proc->next) { + if (!define_printed(proc, def->def.pr.versions)) { + puldefine(proc->proc_name, proc->proc_num); } - f_print(fout, "#endif /* K&R C */\n"); + f_print(fout, "%s", ext); + pprocdef(proc, vers, "CLIENT *", 0); + f_print(fout, "%s", ext); + pprocdef(proc, vers, "struct svc_req *", 1); } + pfreeprocdef(def->def_name, vers->vers_num); } } static void -pprocdef(proc_list *proc, version_list *vp, char* addargtype, int server_p, - int mode) +pprocdef(proc_list *proc, version_list *vp, const char *addargtype, int server_p) { if (mtflag) { /* Print MT style stubs */ @@ -355,20 +320,14 @@ pprocdef(proc_list *proc, version_list *vp, char* addargtype, int server_p, else pvname(proc->proc_name, vp->vers_num); - /* - * mode 1 = ANSI-C, mode 2 = K&R C - */ - if ( mode == 1) - parglist(proc, addargtype); - else - f_print(fout, "();\n"); + parglist(proc, addargtype); } /* print out argument list of procedure */ static void -parglist(proc_list *proc, char* addargtype) +parglist(proc_list *proc, const char *addargtype) { decl_list *dl; @@ -398,9 +357,9 @@ parglist(proc_list *proc, char* addargtype) static void penumdef(definition *def) { - char *name = def->def_name; + const char *name = def->def_name; enumval_list *l; - char *last = NULL; + const char *last = NULL; int count = 0; f_print(fout, "enum %s {\n", name); @@ -428,8 +387,8 @@ penumdef(definition *def) static void ptypedef(definition *def) { - char *name = def->def_name; - char *old = def->def.ty.old_type; + const char *name = def->def_name; + const char *old = def->def.ty.old_type; char prefix[8]; /* enough to contain "struct ", including NUL */ relation rel = def->def.ty.rel; @@ -470,11 +429,11 @@ ptypedef(definition *def) } void -pdeclaration(char *name, declaration *dec, int tab, char *separator) +pdeclaration(const char *name, declaration *dec, int tab, const char *separator) { char buf[8]; /* enough to hold "struct ", include NUL */ - char *prefix; - char *type; + const char *prefix; + const char *type; if (streq(dec->type, "void")) return; @@ -525,7 +484,7 @@ pdeclaration(char *name, declaration *dec, int tab, char *separator) } static int -undefined2(char *type, char *stop) +undefined2(const char *type, const char *stop) { list *l; definition *def; diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c index 570848c5d9..4c58e2ed2e 100644 --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -5,35 +5,33 @@ * 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 * - * @(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI - * $FreeBSD: src/usr.bin/rpcgen/rpc_main.c,v 1.11 1999/08/28 01:05:16 peter Exp $ + * @(#)rpc_main.c 1.21 94/04/25 SMI; 1.30 89/03/30 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_main.c,v 1.33 2007/08/23 09:38:26 delphij Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_main.c,v 1.12 2008/10/16 01:52:33 swildner Exp $ */ -#ident "@(#)rpc_main.c 1.21 94/04/25 SMI" - /* * rpc_main.c, Top level of the RPC protocol compiler. * Copyright (C) 1987, Sun Microsystems, Inc. @@ -49,43 +47,40 @@ #include #include #include "rpc_parse.h" -#include "rpc_util.h" #include "rpc_scan.h" +#include "rpc_util.h" -extern void write_sample_svc(definition *); -extern int write_sample_clnt(definition *); -extern void write_sample_clnt_main(void); -extern void add_sample_msg(void); -static void c_output(char *, char *, int, char *); -static void h_output(char *, char *, int, char *); -static void l_output(char *, char *, int, char *); -static void t_output(char *, char *, int, char *); -static void clnt_output(char *, char *, int, char *); - -void c_initialize(void); +static void c_output(const char *, const char *, int, const char *); +static void h_output(const char *, const char *, int, const char *, int); +static void l_output(const char *, const char *, int, const char *); +static void t_output(const char *, const char *, int, const char *); +static void clnt_output(const char *, const char *, int, const char *); +static char *generate_guard(const char *); +static void c_initialize(void); static void usage(void); static void options_usage(void); -static int do_registers(int, char **); -static int parseargs(int, char **, struct commandline *); -static void svc_output(char *, char *, int, char *); +static int do_registers(int, const char **); +static int parseargs(int, const char **, struct commandline *); +static void svc_output(const char *, const char *, int, const char *); static void mkfile_output(struct commandline *); -static void s_output(int, char **, char *, char *, int, char *, int, int); +static void s_output(int, const char **, const char *, const char *, int, + const char *, int, int); #define EXTEND 1 /* alias for TRUE */ #define DONT_EXTEND 0 /* alias for FALSE */ static int cppDefined = 0; /* explicit path for C preprocessor */ -static char *svcclosetime = "120"; -static char *CPP = NULL; -static char CPPFLAGS[] = "-C"; +static const char *svcclosetime = "120"; +static const char *CPP = NULL; +static const char CPPFLAGS[] = "-C"; static char pathbuf[MAXPATHLEN + 1]; -static char *allv[] = { +static const char *allv[] = { "rpcgen", "-s", "udp", "-s", "tcp", }; static int allc = sizeof (allv)/sizeof (allv[0]); -static char *allnv[] = { +static const char *allnv[] = { "rpcgen", "-s", "netpath", }; static int allnc = sizeof (allnv)/sizeof (allnv[0]); @@ -93,10 +88,11 @@ static int allnc = sizeof (allnv)/sizeof (allnv[0]); /* * machinations for handling expanding argument list */ -static void addarg(); /* add another argument to the list */ -static void putarg(); /* put argument at specified location */ -static void clear_args(); /* clear argument list */ -static void checkfiles(); /* check if out file already exists */ +static void addarg(const char *); /* add another argument to the list */ +static void putarg(int, const char *); /* put argument at specified location */ +static void clear_args(void); /* clear argument list */ +static void checkfiles(const char *, const char *); + /* check if out file already exists */ @@ -108,15 +104,17 @@ static int argcount = FIXEDARGS; int nonfatalerrors; /* errors */ -int inetdflag = 0; /* Support for inetd is now the default */ -int pmflag; /* Support for port monitors */ +int inetdflag = 0; /* Support for inetd is disabled by default, use -I */ +int pmflag = 0; /* Support for port monitors is disabled by default */ +int tirpc_socket = 1; /* TI-RPC on socket, no TLI library */ int logflag; /* Use syslog instead of fprintf for errors */ int tblflag; /* Support for dispatch table file */ int mtflag = 0; /* Support for MT */ + #define INLINE 0 /* length at which to start doing an inline */ -int rpcgen_inline = INLINE; +int inline_size = INLINE; /* * Length at which to start doing an inline. INLINE = default * if 0, no xdr_inline code @@ -126,17 +124,16 @@ int indefinitewait; /* If started by port monitors, hang till it wants */ int exitnow; /* If started by port monitors, exit after the call */ int timerflag; /* TRUE if !indefinite && !exitnow */ 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 */ -int tirpcflag = 0; /* generating code for tirpc, by default */ +int tirpcflag = 1; /* generating code for tirpc, by default */ xdrfunc *xdrfunc_head = NULL; /* xdr function list */ xdrfunc *xdrfunc_tail = NULL; /* xdr function list */ pid_t childpid; int -main(int argc, char **argv) +main(int argc, const char **argv) { struct commandline cmd; @@ -157,7 +154,8 @@ main(int argc, char **argv) if (cmd.cflag) { c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); } else if (cmd.hflag) { - h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile, + cmd.hflag); } else if (cmd.lflag) { l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) { @@ -177,7 +175,7 @@ main(int argc, char **argv) /* the rescans are required, since cpp may effect input */ c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); reinitialize(); - h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h"); + h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h", cmd.hflag); reinitialize(); l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); reinitialize(); @@ -189,7 +187,7 @@ main(int argc, char **argv) EXTEND, "_svc.c", cmd.mflag, cmd.nflag); if (tblflag) { reinitialize(); - t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); + t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); } if (allfiles) { @@ -216,19 +214,17 @@ main(int argc, char **argv) * add extension to filename */ static char * -extendfile(char *path, char *ext) +extendfile(const char *path, const char *ext) { char *res; - char *p; - char *file; + const char *p; + const char *file; if ((file = strrchr(path, '/')) == NULL) file = path; else file++; - res = alloc(strlen(file) + strlen(ext) + 1); - if (res == NULL) - abort(); + res = xmalloc(strlen(file) + strlen(ext) + 1); p = strrchr(file, '.'); if (p == NULL) p = file + strlen(file); @@ -241,7 +237,7 @@ extendfile(char *path, char *ext) * Open output file with given extension */ static void -open_output(char *infile, char *outfile) +open_output(const char *infile, const char *outfile) { if (outfile == NULL) { fout = stdout; @@ -294,7 +290,7 @@ find_cpp(void) * Open input file with given define for C-preprocessor */ static void -open_input(char *infile, char *define) +open_input(const char *infile, const char *define) { int pd[2]; int usevp; @@ -330,7 +326,7 @@ open_input(char *infile, char *define) } /* valid tirpc nettypes */ -static char* valid_ti_nettypes[] = +static const char *valid_ti_nettypes[] = { "netpath", "visible", @@ -345,7 +341,7 @@ static char* valid_ti_nettypes[] = }; /* valid inetd nettypes */ -static char* valid_i_nettypes[] = +static const char *valid_i_nettypes[] = { "udp", "tcp", @@ -353,7 +349,7 @@ static char* valid_i_nettypes[] = }; static int -check_nettype(char *name, char *list_to_check[]) +check_nettype(const char *name, const char *list_to_check[]) { int i; for (i = 0; list_to_check[i] != NULL; i++) { @@ -364,8 +360,8 @@ check_nettype(char *name, char *list_to_check[]) return(0); } -static char * -file_name(char *file, char *ext) +static const char * +file_name(const char *file, const char *ext) { char *temp; temp = extendfile(file, ext); @@ -373,16 +369,16 @@ file_name(char *file, char *ext) if (access(temp, F_OK) != -1) return(temp); else - return((char *)" "); + return(" "); } static void -c_output(char *infile, char *define, int extend, char *outfile) +c_output(const char *infile, const char *define, int extend, const char *outfile) { definition *def; char *include; - char *outfilename; + const char *outfilename; long tell; c_initialize(); @@ -416,7 +412,7 @@ c_initialize(void) add_type(1, "u_short"); } -char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ +const char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ char *(*proc)(); \n\ xdrproc_t xdr_arg; \n\ unsigned len_arg; \n\ @@ -425,19 +421,44 @@ char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ }; \n"; char * -generate_guard(char *pathname) +generate_guard(const char *pathname) { - char* filename, *guard, *tmp; + const char *filename; + char *guard, *tmp, *stopat; filename = strrchr(pathname, '/'); /* find last component */ filename = ((filename == 0) ? pathname : filename+1); - guard = strdup(filename); - /* convert to upper case */ - tmp = guard; - while (*tmp) { + guard = xstrdup(filename); + stopat = strrchr(guard, '.'); + + /* + * Convert to a valid C macro name and make it upper case. + * Map macro unfriendly characterss to '_'. + */ + for (tmp = guard; *tmp != '\000'; ++tmp) { if (islower(*tmp)) *tmp = toupper(*tmp); - tmp++; + else if (isupper(*tmp) || *tmp == '_') + /* OK for C */; + else if (tmp == guard) + *tmp = '_'; + else if (isdigit(*tmp)) + /* OK for all but first character */; + else if (tmp == stopat) { + *tmp = '\0'; + break; + } else + *tmp = '_'; + } + /* + * Can't have a '_' in front, because it'll end up being "__". + * "__" macros shoudln't be used. So, remove all of the + * '_' characters from the front. + */ + if (*guard == '_') { + for (tmp = guard; *tmp == '_'; ++tmp) + ; + strcpy(guard, tmp); } guard = extendfile(guard, "_H_RPCGEN"); return(guard); @@ -448,15 +469,14 @@ generate_guard(char *pathname) */ static void -h_output(char *infile, char *define, int extend, char *outfile) +h_output(const char *infile, const char *define, int extend, const char *outfile, int headeronly) { definition *def; - char *outfilename; + const char *outfilename; long tell; - char *guard; + const char *guard; list *l; xdrfunc *xdrfuncp; - int i; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; @@ -476,7 +496,7 @@ h_output(char *infile, char *define, int extend, char *outfile) f_print(fout, "#include \n"); /* put the C++ support */ - if (Cflag && !CCflag){ + if (!CCflag) { f_print(fout, "\n#ifdef __cplusplus\n"); f_print(fout, "extern \"C\" {\n"); f_print(fout, "#endif\n\n"); @@ -488,7 +508,7 @@ h_output(char *infile, char *define, int extend, char *outfile) /* print data definitions */ while ((def = get_definition()) != 0) - print_datadef(def); + print_datadef(def, headeronly); /* * print function declarations. @@ -496,40 +516,21 @@ h_output(char *infile, char *define, int extend, char *outfile) * arguments for functions */ for (l = defined; l != NULL; l = l->next) - print_funcdef(l->val); - + print_funcdef(l->val, headeronly); /* Now print all xdr func declarations */ if (xdrfunc_head != NULL) { f_print(fout, "\n/* the xdr functions */\n"); if (CCflag) { - f_print(fout, "\n#ifdef __cplusplus\n"); - f_print(fout, "extern \"C\" {\n"); - f_print(fout, "#endif\n"); + f_print(fout, "\n#ifdef __cplusplus\n"); + f_print(fout, "extern \"C\" {\n"); + f_print(fout, "#endif\n"); } - if (!Cflag) { - xdrfuncp = xdrfunc_head; - while (xdrfuncp != NULL) { - print_xdr_func_def(xdrfuncp->name, - xdrfuncp->pointerp, 2); - xdrfuncp = xdrfuncp->next; - } - } else { - for (i = 1; i < 3; i++) { - if (i == 1) - f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); - else - f_print(fout, "\n#else /* K&R C */\n"); - - xdrfuncp = xdrfunc_head; - while (xdrfuncp != NULL) { - print_xdr_func_def(xdrfuncp->name, - xdrfuncp->pointerp, i); - xdrfuncp = xdrfuncp->next; - } - } - f_print(fout, "\n#endif /* K&R C */\n"); + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL) { + print_xdr_func_def(xdrfuncp->name, xdrfuncp->pointerp); + xdrfuncp = xdrfuncp->next; } } @@ -538,11 +539,9 @@ h_output(char *infile, char *define, int extend, char *outfile) else if (tblflag) f_print(fout, rpcgen_table_dcl); - if (Cflag) { - f_print(fout, "\n#ifdef __cplusplus\n"); - f_print(fout, "}\n"); - f_print(fout, "#endif\n"); - } + f_print(fout, "\n#ifdef __cplusplus\n"); + f_print(fout, "}\n"); + f_print(fout, "#endif\n"); f_print(fout, "\n#endif /* !_%s */\n", guard); } @@ -551,13 +550,13 @@ h_output(char *infile, char *define, int extend, char *outfile) * Compile into an RPC service */ static void -s_output(int argc, char **argv, char *infile, char *define, int extend, - char *outfile, int nomain, int netflag) +s_output(int argc, const char **argv, const char *infile, const char *define, + int extend, const char *outfile, int nomain, int netflag) { char *include; definition *def; int foundprogram = 0; - char *outfilename; + const char *outfilename; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; @@ -571,11 +570,10 @@ s_output(int argc, char **argv, char *infile, char *define, int extend, f_print(fout, "#include \n"); f_print(fout, "#include /* getenv, exit */\n"); - if (Cflag) { - f_print(fout, - "#include /* for pmap_unset */\n"); - f_print(fout, "#include /* strcmp */\n"); - } + f_print(fout, "#include /* for pmap_unset */\n"); + f_print(fout, "#include /* strcmp */\n"); + if (tirpcflag) + f_print(fout, "#include \n"); if (strcmp(svcclosetime, "-1") == 0) indefinitewait = 1; else if (strcmp(svcclosetime, "0") == 0) @@ -587,20 +585,19 @@ s_output(int argc, char **argv, char *infile, char *define, int extend, if (!tirpcflag && inetdflag) f_print(fout, "#include /* TIOCNOTTY */\n"); - if (Cflag && (inetdflag || pmflag)) { + if (inetdflag || pmflag) { f_print(fout, "#ifdef __cplusplus\n"); f_print(fout, - "#include /* getdtablesize, open */\n"); + "#include /* getdtablesize, open */\n"); f_print(fout, "#endif /* __cplusplus */\n"); - if (tirpcflag) - f_print(fout, "#include /* setsid */\n"); } - if (tirpcflag) + if (tirpcflag) { + f_print(fout, "#include /* open */\n"); + f_print(fout, "#include /* fork / setsid */\n"); f_print(fout, "#include \n"); + } - f_print(fout, "#include \n"); - if (tirpcflag) - f_print(fout, "#include \n"); + f_print(fout, "#include \n"); if (inetdflag || !tirpcflag) { f_print(fout, "#include \n"); f_print(fout, "#include \n"); @@ -610,15 +607,9 @@ s_output(int argc, char **argv, char *infile, char *define, int extend, f_print(fout, "#include \n"); if (tirpcflag) f_print(fout, "#include /* rlimit */\n"); - if (logflag || inetdflag || pmflag) + if (logflag || inetdflag || pmflag || tirpcflag) f_print(fout, "#include \n"); - /* for ANSI-C */ - if (Cflag) - f_print(fout, - "\n#ifndef SIG_PF\n#define SIG_PF void(*)\ -(int)\n#endif\n"); - f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); if (timerflag) f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", @@ -644,19 +635,18 @@ s_output(int argc, char **argv, char *infile, char *define, int extend, * generate client side stubs */ static void -l_output(char *infile, char *define, int extend, char *outfile) +l_output(const char *infile, const char *define, int extend, const char *outfile) { char *include; definition *def; int foundprogram = 0; - char *outfilename; + const char *outfilename; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; open_output(infile, outfilename); add_warning(); - if (Cflag) - f_print (fout, "#include /* for memset */\n"); + f_print(fout, "#include /* for memset */\n"); if (infile && (include = extendfile(infile, ".h"))) { f_print(fout, "#include \"%s\"\n", include); free(include); @@ -674,11 +664,11 @@ l_output(char *infile, char *define, int extend, char *outfile) * generate the dispatch table */ static void -t_output(char *infile, char *define, int extend, char *outfile) +t_output(const char *infile, const char *define, int extend, const char *outfile) { definition *def; int foundprogram = 0; - char *outfilename; + const char *outfilename; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; @@ -694,11 +684,11 @@ t_output(char *infile, char *define, int extend, char *outfile) /* sample routine for the server template */ static void -svc_output(char *infile, char *define, int extend, char *outfile) +svc_output(const char *infile, const char *define, int extend, const char *outfile) { definition *def; char *include; - char *outfilename; + const char *outfilename; long tell; open_input(infile, define); outfilename = extend ? extendfile(infile, outfile) : outfile; @@ -725,11 +715,11 @@ svc_output(char *infile, char *define, int extend, char *outfile) /* sample main routine for client */ static void -clnt_output(char *infile, char *define, int extend, char *outfile) +clnt_output(const char *infile, const char *define, int extend, const char *outfile) { definition *def; char *include; - char *outfilename; + const char *outfilename; long tell; int has_program = 0; @@ -763,9 +753,9 @@ clnt_output(char *infile, char *define, int extend, char *outfile) static void mkfile_output(struct commandline *cmd) { - char *mkfilename, *clientname, *clntname, *xdrname, *hdrname; - char *servername, *svcname, *servprogname, *clntprogname; - char *temp; + const char *mkfilename, *clientname, *clntname, *xdrname, *hdrname; + const char *servername, *svcname, *servprogname, *clntprogname; + char *temp, *mkftemp; svcname = file_name(cmd->infile, "_svc.c"); clntname = file_name(cmd->infile, "_clnt.c"); @@ -783,11 +773,12 @@ mkfile_output(struct commandline *cmd) clntprogname = extendfile(cmd->infile, "_client"); if (allfiles) { - mkfilename = alloc(strlen("makefile.") + + mkftemp = xmalloc(strlen("makefile.") + strlen(cmd->infile) + 1); temp = strrchr(cmd->infile, '.'); - strcat(mkfilename, "makefile."); - strncat(mkfilename, cmd->infile, (temp - cmd->infile)); + strcpy(mkftemp, "makefile."); + strncat(mkftemp, cmd->infile, (temp - cmd->infile)); + mkfilename = mkftemp; } else mkfilename = cmd->outfile; @@ -821,10 +812,8 @@ mkfile_output(struct commandline *cmd) f_print(fout, "\n# Compiler flags \n"); if (mtflag) - f_print(fout, "\nCPPFLAGS += -D_REENTRANT\n" - "CFLAGS += -g \nLDLIBS += -lnsl -lthread\n"); - else - f_print(fout, "\nCFLAGS += -g \nLDLIBS +=\n"); + f_print(fout, "\nCFLAGS += -D_REENTRANT -D_THEAD_SAFE \nLDLIBS += -pthread\n"); + f_print(fout, "RPCGENFLAGS = \n"); f_print(fout, "\n# Targets \n\n"); @@ -852,7 +841,7 @@ mkfile_output(struct commandline *cmd) * Return 0 if failed; 1 otherwise. */ static int -do_registers(int argc, char **argv) +do_registers(int argc, const char **argv) { int i; @@ -886,26 +875,32 @@ do_registers(int argc, char **argv) * Add another argument to the arg list */ static void -addarg(char *cp) +addarg(const char *cp) { if (argcount >= ARGLISTLEN) { warnx("too many defines"); crash(); /*NOTREACHED*/ } - arglist[argcount++] = cp; + if (cp != NULL) + arglist[argcount++] = xstrdup(cp); + else + arglist[argcount++] = NULL; } static void -putarg(int where, char *cp) +putarg(int place, const char *cp) { - if (where >= ARGLISTLEN) { + if (place >= ARGLISTLEN) { warnx("arglist coding error"); crash(); /*NOTREACHED*/ } - arglist[where] = cp; + if (cp != NULL) + arglist[place] = xstrdup(cp); + else + arglist[place] = NULL; } /* @@ -915,7 +910,7 @@ putarg(int where, char *cp) */ static void -checkfiles(char *infile, char *outfile) +checkfiles(const char *infile, const char *outfile) { struct stat buf; @@ -937,7 +932,7 @@ checkfiles(char *infile, char *outfile) * Parse command line arguments */ static int -parseargs(int argc, char **argv,struct commandline *cmd) +parseargs(int argc, const char **argv, struct commandline *cmd) { int i; int j; @@ -1007,7 +1002,6 @@ parseargs(int argc, char **argv,struct commandline *cmd) flag[(int)ch] = 1; break; case 'C': /* ANSI C syntax */ - Cflag = 1; ch = argv[i][j+1]; /* get next char */ if (ch != 'C') @@ -1015,7 +1009,12 @@ parseargs(int argc, char **argv,struct commandline *cmd) CCflag = 1; break; case 'b': - tirpcflag = 1; + /* + * Turn TIRPC flag off for + * generating backward compatible + * code + */ + tirpcflag = 0; break; case 'I': @@ -1027,6 +1026,9 @@ parseargs(int argc, char **argv,struct commandline *cmd) case 'L': logflag = 1; break; + case 'P': + pmflag = 1; + break; case 'K': if (++i == argc) return(0); @@ -1041,7 +1043,7 @@ parseargs(int argc, char **argv,struct commandline *cmd) case 'i' : if (++i == argc) return(0); - rpcgen_inline = atoi(argv[i]); + inline_size = atoi(argv[i]); goto nextarg; case 'n': case 'o': @@ -1066,8 +1068,12 @@ parseargs(int argc, char **argv,struct commandline *cmd) case 'Y': if (++i == argc) return(0); - strcpy(pathbuf, argv[i]); - strcat(pathbuf, "/cpp"); + strlcpy(pathbuf, argv[i], sizeof(pathbuf)); + if (strlcat(pathbuf, "/cpp", sizeof(pathbuf)) + >= sizeof(pathbuf)) { + warnx("argument too long"); + return (0); + } CPP = pathbuf; cppDefined = 1; goto nextarg; @@ -1093,8 +1099,8 @@ parseargs(int argc, char **argv,struct commandline *cmd) cmd->makefileflag = flag['M']; if (tirpcflag) { - pmflag = inetdflag ? 0 : 1; - /* pmflag or inetdflag is always TRUE */ + if (inetdflag) + pmflag = 0; if ((inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */ warnx("cannot use netid flag with inetd flag"); @@ -1135,10 +1141,10 @@ parseargs(int argc, char **argv,struct commandline *cmd) static void usage(void) { - f_print(stderr, "%s\n%s\n%s\n%s\n%s\n", + f_print(stderr, "%s\n%s\n%s\n%s\n%s\n", "usage: rpcgen infile", " rpcgen [-abCLNTM] [-Dname[=value]] [-i size]" - "[-I [-K seconds]] [-Y path] infile", + "[-I -P [-K seconds]] [-Y path] infile", " rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]" "[-o outfile] [infile]", " rpcgen [-s nettype]* [-o outfile] [infile]", @@ -1160,8 +1166,7 @@ options_usage(void) f_print(stderr, "-h\t\tgenerate header file\n"); f_print(stderr, "-i size\t\tsize at which to start generating" "inline code\n"); - f_print(stderr, "-I\t\tgenerate code for inetd support in server" - "(for SunOS 4.X)\n"); + f_print(stderr, "-I\t\tgenerate code for inetd support in server\n"); f_print(stderr, "-K seconds\tserver exits after K seconds of" "inactivity\n"); f_print(stderr, "-l\t\tgenerate client side stubs\n"); @@ -1173,6 +1178,7 @@ options_usage(void) f_print(stderr, "-N\t\tsupports multiple arguments and" "call-by-value\n"); f_print(stderr, "-o outfile\tname of the output file\n"); + f_print(stderr, "-P\t\tgenerate code for port monitoring support in server\n"); f_print(stderr, "-s nettype\tgenerate server code that supports named" "nettype\n"); f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote" diff --git a/usr.bin/rpcgen/rpc_parse.c b/usr.bin/rpcgen/rpc_parse.c index a189b68807..b942992527 100644 --- a/usr.bin/rpcgen/rpc_parse.c +++ b/usr.bin/rpcgen/rpc_parse.c @@ -5,33 +5,32 @@ * 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 * - * @(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI + * @(#)rpc_parse.c 1.12 93/07/05 SMI; 1.8 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_parse.c,v 1.12 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_parse.c,v 1.7 2004/06/19 16:40:36 joerg Exp $ */ -#ident "@(#)rpc_parse.c 1.12 93/07/05 SMI" - /* * rpc_parse.c, Parser for the RPC protocol compiler * Copyright (C) 1987 Sun Microsystems, Inc. @@ -39,24 +38,23 @@ #include #include #include "rpc/types.h" -#include "rpc_scan.h" #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" #define ARGNAME "arg" -extern char *make_argname(char *, char *); static void isdefined(definition *); static void def_struct(definition *); static void def_program(definition *); static void def_enum(definition *); static void def_const(definition *); static void def_union(definition *); -static void def_typedef( definition *); -static void get_declaration( declaration *, defkind); -static void get_prog_declaration( declaration *, defkind, int); -static void get_type(char **, char **, defkind); -static void unsigned_dec(char **); +static void def_typedef(definition *); +static void get_declaration(declaration *, defkind); +static void get_prog_declaration(declaration *, defkind, int); +static void get_type(const char **, const char **, defkind); +static void unsigned_dec(const char **); /* * return the next definition you see @@ -67,7 +65,7 @@ get_definition(void) definition *defp; token tok; - defp = ALLOC(definition); + defp = XALLOC(definition); get_token(&tok); switch (tok.kind) { case TOK_STRUCT: @@ -120,7 +118,7 @@ def_struct(definition *defp) tailp = &defp->def.st.decls; do { get_declaration(&dec, DEF_STRUCT); - decls = ALLOC(decl_list); + decls = XALLOC(decl_list); decls->decl = dec; *tailp = decls; tailp = &decls->next; @@ -153,13 +151,13 @@ def_program(definition *defp) scan(TOK_VERSION, &tok); do { scan(TOK_IDENT, &tok); - vlist = ALLOC(version_list); + vlist = XALLOC(version_list); vlist->vers_name = tok.str; scan(TOK_LBRACE, &tok); ptailp = &vlist->procs; do { /* get result type */ - plist = ALLOC(proc_list); + plist = XALLOC(proc_list); get_type(&plist->res_prefix, &plist->res_type, DEF_PROGRAM); if (streq(plist->res_type, "opaque")) @@ -178,7 +176,7 @@ def_program(definition *defp) get_prog_declaration(&dec, DEF_PROGRAM, num_args); if (streq(dec.type, "void")) isvoid = TRUE; - decls = ALLOC(decl_list); + decls = XALLOC(decl_list); plist->args.decls = decls; decls->decl = dec; tailp = &decls->next; @@ -187,7 +185,7 @@ def_program(definition *defp) num_args++; get_prog_declaration(&dec, DEF_STRUCT, num_args); - decls = ALLOC(decl_list); + decls = XALLOC(decl_list); decls->decl = dec; *tailp = decls; if (streq(dec.type, "void")) @@ -247,7 +245,7 @@ def_enum(definition *defp) tailp = &defp->def.en.vals; do { scan(TOK_IDENT, &tok); - elist = ALLOC(enumval_list); + elist = XALLOC(enumval_list); elist->name = tok.str; elist->assignment = NULL; scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); @@ -297,7 +295,7 @@ def_union(definition *defp) scan(TOK_CASE, &tok); while (tok.kind == TOK_CASE) { scan2(TOK_IDENT, TOK_CHARCONST, &tok); - cases = ALLOC(case_list); + cases = XALLOC(case_list); cases->case_name = tok.str; scan(TOK_COLON, &tok); /* now peek at next token */ @@ -309,7 +307,7 @@ def_union(definition *defp) /* continued case statement */ *tailp = cases; tailp = &cases->next; - cases = ALLOC(case_list); + cases = XALLOC(case_list); cases->case_name = tok.str; scan(TOK_COLON, &tok); } while (peekscan(TOK_CASE, &tok)); @@ -317,7 +315,7 @@ def_union(definition *defp) else if (flag) { *tailp = cases; tailp = &cases->next; - cases = ALLOC(case_list); + cases = XALLOC(case_list); } get_declaration(&dec, DEF_UNION); @@ -333,7 +331,7 @@ def_union(definition *defp) if (tok.kind == TOK_DEFAULT) { scan(TOK_COLON, &tok); get_declaration(&dec, DEF_UNION); - defp->def.un.default_decl = ALLOC(declaration); + defp->def.un.default_decl = XALLOC(declaration); *defp->def.un.default_decl = dec; scan(TOK_SEMICOLON, &tok); scan(TOK_RBRACE, &tok); @@ -342,7 +340,7 @@ def_union(definition *defp) } } -static char* reserved_words[] = +static const char *reserved_words[] = { "array", "bytes", @@ -357,9 +355,9 @@ static char* reserved_words[] = "union", "vector", NULL - }; +}; -static char* reserved_types[] = +static const char *reserved_types[] = { "opaque", "string", @@ -371,7 +369,7 @@ static char* reserved_types[] = * xdr routines that would conflict with internal XDR routines. */ static void -check_type_name(char* name, int new_type) +check_type_name(const char *name, int new_type) { int i; char tmp[100]; @@ -485,7 +483,7 @@ get_prog_declaration(declaration *dec, defkind dkind, int num) sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */ - dec->name = (char *) strdup(name); + dec->name = (char *) xstrdup(name); if (streq(dec->type, "void")) { return; } @@ -494,11 +492,11 @@ get_prog_declaration(declaration *dec, defkind dkind, int num) error("opaque -- illegal argument type"); if (peekscan(TOK_STAR, &tok)) { if (streq(dec->type, "string")) - error("pointer to string not allowed in program arguments\n"); + error("pointer to string not allowed in program arguments"); dec->rel = REL_POINTER; if (peekscan(TOK_IDENT, &tok)) { /* optional name of argument */ - dec->name = strdup(tok.str); + dec->name = xstrdup(tok.str); } } if (peekscan(TOK_LANGLE, &tok)) { @@ -528,7 +526,7 @@ get_prog_declaration(declaration *dec, defkind dkind, int num) } static void -get_type(char **prefixp, char **typep, defkind dkind) +get_type(const char **prefixp, const char **typep, defkind dkind) { token tok; @@ -582,7 +580,7 @@ get_type(char **prefixp, char **typep, defkind dkind) } static void -unsigned_dec(char **typep) +unsigned_dec(const char **typep) { token tok; diff --git a/usr.bin/rpcgen/rpc_parse.h b/usr.bin/rpcgen/rpc_parse.h index b96091a49f..a24c0df627 100644 --- a/usr.bin/rpcgen/rpc_parse.h +++ b/usr.bin/rpcgen/rpc_parse.h @@ -5,28 +5,31 @@ * 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 + * + * @(#)rpc_parse.h 1.10 94/05/15 SMI; 1.3 90/08/29 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_parse.h,v 1.7 2005/11/13 21:17:24 dwmalone Exp $ + * $DragonFly: src/usr.bin/rpcgen/rpc_parse.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ -#pragma ident "@(#)rpc_parse.h 1.10 94/05/15 SMI" /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ @@ -47,21 +50,18 @@ * * * -* Copyright Notice +* Copyright Notice * -* Notice of copyright on this source code product does not indicate +* Notice of copyright on this source code product does not indicate * publication. * * (c) 1986,1987,1988.1989 Sun Microsystems, Inc * (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. * All rights reserved. -*/ - -/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */ -/* $DragonFly: src/usr.bin/rpcgen/rpc_parse.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ +*/ /* - * rpc_parse.h, Definitions for the RPCL parser + * rpc_parse.h, Definitions for the RPCL parser */ enum defkind { @@ -74,7 +74,7 @@ enum defkind { }; typedef enum defkind defkind; -typedef char *const_def; +typedef const char *const_def; enum relation { REL_VECTOR, /* fixed length array */ @@ -85,16 +85,16 @@ enum relation { typedef enum relation relation; struct typedef_def { - char *old_prefix; - char *old_type; + const char *old_prefix; + const char *old_type; relation rel; - char *array_max; + const char *array_max; }; typedef struct typedef_def typedef_def; struct enumval_list { - char *name; - char *assignment; + const char *name; + const char *assignment; struct enumval_list *next; }; typedef struct enumval_list enumval_list; @@ -105,11 +105,11 @@ struct enum_def { typedef struct enum_def enum_def; struct declaration { - char *prefix; - char *type; - char *name; + const char *prefix; + const char *type; + const char *name; relation rel; - char *array_max; + const char *array_max; }; typedef struct declaration declaration; @@ -125,7 +125,7 @@ struct struct_def { typedef struct struct_def struct_def; struct case_list { - char *case_name; + const char *case_name; int contflag; declaration case_decl; struct case_list *next; @@ -147,32 +147,32 @@ struct arg_list { typedef struct arg_list arg_list; struct proc_list { - char *proc_name; - char *proc_num; + const char *proc_name; + const char *proc_num; arg_list args; int arg_num; - char *res_type; - char *res_prefix; + const char *res_type; + const char *res_prefix; struct proc_list *next; }; typedef struct proc_list proc_list; struct version_list { - char *vers_name; - char *vers_num; + const char *vers_name; + const char *vers_num; proc_list *procs; struct version_list *next; }; typedef struct version_list version_list; struct program_def { - char *prog_num; + const char *prog_num; version_list *versions; }; typedef struct program_def program_def; struct definition { - char *def_name; + const char *def_name; defkind def_kind; union { const_def co; @@ -189,7 +189,7 @@ definition *get_definition(void); struct bas_type { - char *name; + const char *name; int length; struct bas_type *next; }; diff --git a/usr.bin/rpcgen/rpc_sample.c b/usr.bin/rpcgen/rpc_sample.c index d61d057dc2..dc565e320c 100644 --- a/usr.bin/rpcgen/rpc_sample.c +++ b/usr.bin/rpcgen/rpc_sample.c @@ -5,31 +5,32 @@ * 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 + * + * @(#)rpc_sample.c 1.9 94/04/25 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_sample.c,v 1.9 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_sample.c,v 1.4 2004/06/19 16:40:36 joerg Exp $ */ -#pragma ident "@(#)rpc_sample.c 1.9 94/04/25 SMI" - /* * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler * Copyright (C) 1987, Sun Microsystems, Inc. @@ -38,19 +39,20 @@ #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" static char RQSTP[] = "rqstp"; -extern void printarglist(proc_list *, char *, char *, char *); -static void write_sample_client(char *, version_list *); +static void write_sample_client(const char *, version_list *); static void write_sample_server(definition *); static void return_type(proc_list *); void write_sample_svc(definition *def) { - if (def->def_kind != DEF_PROGRAM) + + if (def->def_kind != DEF_PROGRAM) return; write_sample_server(def); } @@ -62,7 +64,7 @@ write_sample_clnt(definition *def) version_list *vp; int count = 0; - if (def->def_kind != DEF_PROGRAM) + if (def->def_kind != DEF_PROGRAM) return(0); /* generate sample code for each version */ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { @@ -74,7 +76,7 @@ write_sample_clnt(definition *def) static void -write_sample_client(char *program_name, version_list *vp) +write_sample_client(const char *program_name, version_list *vp) { proc_list *proc; int i; @@ -82,10 +84,7 @@ write_sample_client(char *program_name, version_list *vp) f_print(fout, "\n\nvoid\n"); pvname(program_name, vp->vers_num); - if(Cflag) - f_print(fout,"(char *host)\n{\n"); - else - f_print(fout, "(host)\n\tchar *host;\n{\n"); + f_print(fout, "(char *host)\n{\n"); f_print(fout, "\tCLIENT *clnt;\n"); i = 0; @@ -103,7 +102,7 @@ write_sample_client(char *program_name, version_list *vp) if(proc->arg_num < 2 && !newstyle) { f_print(fout, "\t"); if(!streq(proc->args.decls->decl.type, "void")) - ptype(proc->args.decls->decl.prefix, + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); else f_print(fout, "char * "); /* cannot have "void" type */ @@ -124,7 +123,7 @@ write_sample_client(char *program_name, version_list *vp) /* generate creation of client handle */ f_print(fout, "\n#ifndef\tDEBUG\n"); - f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", program_name, vp->vers_name, tirpcflag? "netpath" : "udp"); f_print(fout, "\tif (clnt == (CLIENT *) NULL) {\n"); f_print(fout, "\t\tclnt_pcreateerror(host);\n"); @@ -135,9 +134,9 @@ write_sample_client(char *program_name, version_list *vp) i = 0; for (proc = vp->procs; proc != NULL; proc = proc->next) { if (mtflag) - f_print(fout, "\tretval_%d = ",++i); + f_print(fout, "\tretval_%d = ",++i); else - f_print(fout, "\tresult_%d = ",++i); + f_print(fout, "\tresult_%d = ",++i); pvname(proc->proc_name, vp->vers_num); if (proc->arg_num < 2 && !newstyle) { f_print(fout, "("); @@ -199,10 +198,7 @@ write_sample_server(definition *def) f_print(fout, "*\n"); } else f_print(fout, "bool_t\n"); - if (Cflag || mtflag) - pvname_svc(proc->proc_name, vp->vers_num); - else - pvname(proc->proc_name, vp->vers_num); + pvname_svc(proc->proc_name, vp->vers_num); printarglist(proc, "result", RQSTP, "struct svc_req *"); f_print(fout, "{\n"); @@ -214,18 +210,17 @@ write_sample_server(definition *def) f_print(fout, "char *"); /* cannot have void type */ f_print(fout, " result;\n"); - } - else { + } else { f_print(fout, "\tbool_t retval;\n"); } - f_print(fout, + f_print(fout, "\n\t/*\n\t * insert server code here\n\t */\n\n"); if (!mtflag) { if(!streq(proc->res_type, "void")) f_print(fout, "\treturn (&result);\n}\n"); else /* cast back to void * */ - f_print(fout, "\treturn((void *) &result);\n}\n"); + f_print(fout, "\treturn((void *) &result);\n}\n"); } else { f_print(fout, "\treturn (retval);\n}\n"); } @@ -234,18 +229,11 @@ write_sample_server(definition *def) if (mtflag) { f_print(fout, "\nint\n"); pvname(def->def_name, vp->vers_num); - if (Cflag) { - f_print(fout,"_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n"); - } else { - f_print(fout,"_freeresult(transp, xdr_result, result)\n"); - f_print(fout,"\tSVCXPRT *transp;\n"); - f_print(fout,"\txdrproc_t xdr_result;\n"); - f_print(fout,"\tcaddr_t result;\n"); - } + f_print(fout,"_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n"); f_print(fout, "{\n"); - f_print(fout, "\t(void) xdr_free(xdr_result, result);\n"); - f_print(fout, - "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n"); + f_print(fout, "\txdr_free(xdr_result, result);\n"); + f_print(fout, + "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n"); f_print(fout, "\n}\n"); } } @@ -277,11 +265,7 @@ write_sample_clnt_main(void) version_list *vp; f_print(fout, "\n\n"); - if(Cflag) - f_print(fout,"main(int argc, char *argv[])\n{\n"); - else - f_print(fout, "main(argc, argv)\n\tint argc;\n" - "\tchar *argv[];\n{\n"); + f_print(fout, "main(int argc, char *argv[])\n{\n"); f_print(fout, "\tchar *host;"); f_print(fout, "\n\n\tif (argc < 2) {"); diff --git a/usr.bin/rpcgen/rpc_scan.c b/usr.bin/rpcgen/rpc_scan.c index 573b5468a0..11fc3e887e 100644 --- a/usr.bin/rpcgen/rpc_scan.c +++ b/usr.bin/rpcgen/rpc_scan.c @@ -5,38 +5,35 @@ * 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 * - * $FreeBSD: src/usr.bin/rpcgen/rpc_scan.c,v 1.4.8.1 2001/03/04 08:59:50 kris Exp $ + * @(#)rpc_scan.c 1.13 93/07/05 SMI; 1.11 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_scan.c,v 1.10 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_scan.c,v 1.5 2008/10/16 01:52:33 swildner Exp $ - * - * @(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI */ -#ident "@(#)rpc_scan.c 1.13 93/07/05 SMI" - /* - * rpc_scan.c, Scanner for the RPC protocol compiler - * Copyright (C) 1987, Sun Microsystems, Inc. + * rpc_scan.c, Scanner for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. */ #include @@ -45,8 +42,8 @@ #include #include #include -#include "rpc_scan.h" #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" #define startcomment(where) (where[0] == '/' && where[1] == '*') @@ -56,17 +53,17 @@ static int pushed = 0; /* is a token pushed */ static token lasttok; /* last token, if pushed */ static void unget_token(token *); -static void findstrconst(char **, char **); -static void findchrconst(char **, char **); -static void findconst(char **, char **); +static void findstrconst(char **, const char **); +static void findchrconst(char **, const char **); +static void findconst(char **, const char **); static void findkind(char **, token *); static int cppline(char *); static int directive(char *); static void printdirective(char *); -static void docppline(char *, int *, char **); +static void docppline(char *, int *, const char **); /* - * scan expecting 1 given token + * scan expecting 1 given token */ void scan(tok_kind expect, token *tokp) @@ -77,7 +74,7 @@ scan(tok_kind expect, token *tokp) } /* - * scan expecting any of the 2 given tokens + * scan expecting any of the 2 given tokens */ void scan2(tok_kind expect1, tok_kind expect2, token *tokp) @@ -88,7 +85,7 @@ scan2(tok_kind expect1, tok_kind expect2, token *tokp) } /* - * scan expecting any of the 3 given token + * scan expecting any of the 3 given token */ void scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp) @@ -100,7 +97,7 @@ scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp) } /* - * scan expecting a constant, possibly symbolic + * scan expecting a constant, possibly symbolic */ void scan_num(token *tokp) @@ -115,7 +112,7 @@ scan_num(token *tokp) } /* - * Peek at the next token + * Peek at the next token */ void peek(token *tokp) @@ -125,7 +122,7 @@ peek(token *tokp) } /* - * Peek at the next token and scan it if it matches what you expect + * Peek at the next token and scan it if it matches what you expect */ int peekscan(tok_kind expect, token *tokp) @@ -139,14 +136,14 @@ peekscan(tok_kind expect, token *tokp) } /* - * Get the next token, printing out any directive that are encountered. + * Get the next token, printing out any directive that are encountered. */ void get_token(token *tokp) { int commenting; int stat = 0; - + if (pushed) { pushed = 0; *tokp = lasttok; @@ -204,7 +201,7 @@ get_token(token *tokp) } /* - * 'where' is not whitespace, comment or directive Must be a token! + * 'where' is not whitespace, comment or directive Must be a token! */ switch (*where) { case ':': @@ -311,9 +308,10 @@ unget_token(token *tokp) } static void -findstrconst(char **str, char **val) +findstrconst(char **str, const char **val) { char *p; + char *tmp; int size; p = *str; @@ -324,16 +322,18 @@ findstrconst(char **str, char **val) error("unterminated string constant"); p++; size = p - *str; - *val = alloc(size + 1); - (void) strncpy(*val, *str, size); - (*val)[size] = 0; + tmp = xmalloc(size + 1); + strncpy(tmp, *str, size); + tmp[size] = 0; + *val = tmp; *str = p; } static void -findchrconst(char **str, char **val) +findchrconst(char **str, const char **val) { char *p; + char *tmp; int size; p = *str; @@ -346,16 +346,18 @@ findchrconst(char **str, char **val) size = p - *str; if (size != 3) error("empty char string"); - *val = alloc(size + 1); - strncpy(*val, *str, size); - (*val)[size] = 0; + tmp = xmalloc(size + 1); + strncpy(tmp, *str, size); + tmp[size] = 0; + *val = tmp; *str = p; } static void -findconst(char **str, char **val) +findconst(char **str, const char **val) { char *p; + char *tmp; int size; p = *str; @@ -370,9 +372,10 @@ findconst(char **str, char **val) } while (isdigit(*p)); } size = p - *str; - *val = alloc(size + 1); - strncpy(*val, *str, size); - (*val)[size] = 0; + tmp = xmalloc(size + 1); + strncpy(tmp, *str, size); + tmp[size] = 0; + *val = tmp; *str = p; } @@ -408,7 +411,7 @@ findkind(char **mark, token *tokp) { int len; token *s; - char *str; + char *str, *tmp; str = *mark; for (s = symbols; s->kind != TOK_EOF; s++) { @@ -424,9 +427,10 @@ findkind(char **mark, token *tokp) } tokp->kind = TOK_IDENT; for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); - tokp->str = alloc(len + 1); - strncpy(tokp->str, str, len); - tokp->str[len] = 0; + tmp = xmalloc(len + 1); + strncpy(tmp, str, len); + tmp[len] = 0; + tokp->str = tmp; *mark = str + len; } @@ -449,7 +453,7 @@ printdirective(char *line) } static void -docppline(char *line, int *lineno, char **fname) +docppline(char *line, int *lineno, const char **fname) { char *file; int num; @@ -466,7 +470,7 @@ docppline(char *line, int *lineno, char **fname) if (*line != '"') error("preprocessor error"); line++; - p = file = alloc(strlen(line) + 1); + p = file = xmalloc(strlen(line) + 1); while (*line && *line != '"') *p++ = *line++; if (*line == 0) diff --git a/usr.bin/rpcgen/rpc_scan.h b/usr.bin/rpcgen/rpc_scan.h index 32a5bb683c..4a7af1f1ee 100644 --- a/usr.bin/rpcgen/rpc_scan.h +++ b/usr.bin/rpcgen/rpc_scan.h @@ -5,28 +5,31 @@ * 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 + * + * @(#)rpc_scan.h 1.11 94/05/15 SMI; 1.3 90/08/29 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_scan.h,v 1.7 2005/11/13 21:17:24 dwmalone Exp $ + * $DragonFly: src/usr.bin/rpcgen/rpc_scan.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ -#pragma ident "@(#)rpc_scan.h 1.11 94/05/15 SMI" /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ @@ -48,28 +51,25 @@ * * * -* Copyright Notice +* Copyright Notice * -* Notice of copyright on this source code product does not indicate +* Notice of copyright on this source code product does not indicate * publication. * * (c) 1986,1987,1988.1989 Sun Microsystems, Inc * (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. * All rights reserved. -*/ - -/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */ -/* $DragonFly: src/usr.bin/rpcgen/rpc_scan.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ +*/ /* - * rpc_scan.h, Definitions for the RPCL scanner + * rpc_scan.h, Definitions for the RPCL scanner */ -#ifndef RPC_SCAN -#define RPC_SCAN +#ifndef _RPC_SCAN_H_ +#define _RPC_SCAN_H_ /* - * kinds of tokens + * kinds of tokens */ enum tok_kind { TOK_IDENT, @@ -116,24 +116,24 @@ enum tok_kind { typedef enum tok_kind tok_kind; /* - * a token + * a token */ struct token { tok_kind kind; - char *str; + const char *str; }; typedef struct token token; /* - * routine interface + * routine interface */ -void scan(); -void scan2(); -void scan3(); -void scan_num(); -void peek(); -int peekscan(); -void get_token(); +void scan(tok_kind, token *); +void scan2(tok_kind, tok_kind, token *); +void scan3(tok_kind, tok_kind, tok_kind, token *); +void scan_num(token *); +void peek(token *); +int peekscan(tok_kind, token *); +void get_token(token *); -#endif +#endif /* _RPC_SCAN_H_ */ diff --git a/usr.bin/rpcgen/rpc_svcout.c b/usr.bin/rpcgen/rpc_svcout.c index a9dec19088..4f77ad5804 100644 --- a/usr.bin/rpcgen/rpc_svcout.c +++ b/usr.bin/rpcgen/rpc_svcout.c @@ -5,34 +5,32 @@ * 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 * - * @(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI - * $FreeBSD: src/usr.bin/rpcgen/rpc_svcout.c,v 1.6.6.1 2001/07/19 01:38:22 kris Exp $ + * @(#)rpc_svcout.c 1.4 90/04/13 SMI; 1.29 89/03/30 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_svcout.c,v 1.26 2008/08/12 13:38:06 dfr Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_svcout.c,v 1.5 2008/10/16 01:52:33 swildner Exp $ */ -#ident "@(#)rpc_svcout.c 1.4 90/04/13 SMI" - /* * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler * Copyright (C) 1987, Sun Microsystems, Inc. @@ -40,6 +38,7 @@ #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" static char RQSTP[] = "rqstp"; @@ -53,29 +52,25 @@ char _errbuf[256]; /* For all messages */ void internal_proctype(proc_list *); static void write_real_program(definition *); -static void write_program(definition *, char *); -static void printerr(char *, char *); -static void printif(char *, char *, char *, char *); -static void write_inetmost(char *); -static void print_return(char *); -static void print_pmapunset(char *); -static void print_err_message(char *); +static void write_program(definition *, const char *); +static void printerr(const char *, const char *); +static void printif(const char *, const char *, const char *, const char *); +static void write_inetmost(const char *); +static void print_return(const char *); +static void print_pmapunset(const char *); +static void print_err_message(const char *); static void write_timeout_func(void); -static void write_pm_most(char *, int); -static void write_rpc_svc_fg(char *, char *); -static void open_log_file(char *, char *); +static void write_pm_most(const char *, int); +static void write_rpc_svc_fg(const char *, const char *); +static void open_log_file(const char *, const char *); static void write_msg_out(void); -int nullpro(proc_list *); + static void -p_xdrfunc(char* rname, char* typename) +p_xdrfunc(const char *rname, const char *typename) { - if (Cflag) - f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", - rname, stringfix(typename)); - else - f_print(fout, "\t\txdr_%s = xdr_%s;\n", - rname, stringfix(typename)); + f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", + rname, stringfix(typename)); } void @@ -91,14 +86,14 @@ internal_proctype(proc_list *plist) * write most of the service, that is, everything but the registrations. */ void -write_most(char *infile, int netflag, int nomain) +write_most(const char *infile, int netflag, int nomain) { if (inetdflag || pmflag) { - char* var_type; + const char *var_type; var_type = (nomain? "extern" : "static"); f_print(fout, "%s int _rpcpmstart;", var_type); f_print(fout, "\t\t/* Started by a port monitor ? */\n"); - if (!tirpcflag) { + if (!tirpcflag || tirpc_socket) { f_print(fout, "%s int _rpcfdtype;", var_type); f_print(fout, "\n\t\t /* Whether Stream or " "Datagram ? */\n"); @@ -115,9 +110,10 @@ write_most(char *infile, int netflag, int nomain) "serviced */\n"); if (mtflag) { - f_print(fout, "mutex_t _svcstate_lock;"); + f_print(fout, "pthread_mutex_t _svcstate_lock;"); f_print(fout, "\t\t\t/* Mutex lock for " "variable _rpcsvcstate */\n"); + } } @@ -125,12 +121,13 @@ write_most(char *infile, int netflag, int nomain) write_svc_aux(nomain); } /* write out dispatcher and stubs */ - write_programs(nomain? (char *)NULL : "static"); + write_programs((char *)NULL); if (nomain) return; - f_print(fout, "\nmain()\n"); + f_print(fout, "\nint\n"); + f_print(fout, "main()\n"); f_print(fout, "{\n"); if (inetdflag) { write_inetmost(infile); @@ -145,16 +142,25 @@ write_most(char *infile, int netflag, int nomain) } f_print(fout, "\tpid_t pid;\n"); f_print(fout, "\tint i;\n"); - f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + if (pmflag) { + if (tirpc_socket) { + f_print(fout, "\tstruct sockaddr_storage saddr;\n"); + f_print(fout, "\tsocklen_t asize = sizeof (saddr);\n\n"); + } else + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + } if (mtflag & timerflag) f_print(fout, "\tmutex_init(&_svcstate_lock, " "USYNC_THREAD, NULL);\n"); + if (pmflag) { + write_pm_most(infile, netflag); + f_print(fout, "\telse {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t}\n"); + } else + write_rpc_svc_fg(infile, "\t\t"); - write_pm_most(infile, netflag); - f_print(fout, "\telse {\n"); - write_rpc_svc_fg(infile, "\t\t"); - f_print(fout, "\t}\n"); } else { f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); f_print(fout, "\n"); @@ -170,12 +176,12 @@ write_most(char *infile, int netflag, int nomain) * write a registration for the given transport */ void -write_netid_register(char *transp) +write_netid_register(const char *transp) { list *l; definition *def; version_list *vp; - char *sp; + const char *sp; char tmpbuf[32]; sp = ""; @@ -187,8 +193,15 @@ write_netid_register(char *transp) print_err_message(tmpbuf); f_print(fout, "%s\t\texit(1);\n", sp); f_print(fout, "%s\t}\n", sp); - f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", - sp, TRANSP); + if (tirpcflag) { + f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, ", + sp, TRANSP); + f_print(fout,"nconf, 0, RPC_MAXDATASIZE, RPC_MAXDATASIZE);\n"); + } else { + f_print(fout, + "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", + sp, TRANSP); + } f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); sprintf(_errbuf, "cannot create %s service.", transp); print_err_message(tmpbuf); @@ -200,7 +213,7 @@ write_netid_register(char *transp) if (def->def_kind != DEF_PROGRAM) continue; for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { - f_print(fout, "%s\t(void) rpcb_unset(%s, %s, nconf);\n", + f_print(fout, "%s\trpcb_unset(%s, %s, nconf);\n", sp, def->def_name, vp->vers_name); f_print(fout, "%s\tif (!svc_reg(%s, %s, %s, ", sp, TRANSP, def->def_name, vp->vers_name); @@ -220,7 +233,7 @@ write_netid_register(char *transp) * write a registration for the given transport for TLI */ void -write_nettype_register(char *transp) +write_nettype_register(const char *transp) { list *l; definition *def; @@ -253,15 +266,14 @@ write_rest(void) f_print(fout, "\n"); if (inetdflag) { f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); - sprintf(_errbuf, "could not create a handle"); + sprintf(_errbuf, "could not create a handle"); print_err_message("\t\t"); f_print(fout, "\t\texit(1);\n"); f_print(fout, "\t}\n"); if (timerflag) { f_print(fout, "\tif (_rpcpmstart) {\n"); f_print(fout, - "\t\tsignal(SIGALRM, %s closedown);\n", - Cflag? "(SIG_PF)":"(void(*)())"); + "\t\tsignal(SIGALRM, closedown);\n"); f_print(fout, "\t\talarm(_RPCSVC_CLOSEDOWN/2);\n"); f_print(fout, "\t}\n"); } @@ -275,7 +287,7 @@ write_rest(void) } void -write_programs(char *storage) +write_programs(const char *storage) { list *l; definition *def; @@ -319,48 +331,24 @@ write_real_program(definition *def) f_print(fout, "int"); f_print(fout, "\n_"); pvname(proc->proc_name, vp->vers_num); - if (Cflag) { - f_print(fout, "("); - /* arg name */ - if (proc->arg_num > 1) - f_print(fout, proc->args.argname); - else - ptype(proc->args.decls->decl.prefix, - proc->args.decls->decl.type, 0); - if (mtflag) { - f_print(fout, " *argp, void *%s, struct svc_req *%s)\n", - RESULT, RQSTP); - } - else - f_print(fout, " *argp, struct svc_req *%s)\n", - RQSTP); - - } else { - if (mtflag) - f_print(fout, "(argp, %s, %s)\n", RESULT, RQSTP); - else - f_print(fout, "(argp, %s)\n", RQSTP); - /* arg name */ - if (proc->arg_num > 1) - f_print(fout, "\t%s *argp;\n", - proc->args.argname); - else { - f_print(fout, "\t"); - ptype(proc->args.decls->decl.prefix, - proc->args.decls->decl.type, 0); - f_print(fout, " *argp;\n"); - } - if (mtflag) - f_print(fout, "\tvoid *%s;\n", RESULT); - f_print(fout, "\tstruct svc_req *%s;\n", RQSTP); + f_print(fout, "("); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, proc->args.argname); + else + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + if (mtflag) { + f_print(fout, " *argp, void *%s, struct svc_req *%s)\n", + RESULT, RQSTP); } + else + f_print(fout, " *argp, struct svc_req *%s)\n", + RQSTP); f_print(fout, "{\n"); f_print(fout, "\treturn ("); - if (Cflag || mtflag) /* for mtflag, arguments are different */ - pvname_svc(proc->proc_name, vp->vers_num); - else - pvname(proc->proc_name, vp->vers_num); + pvname_svc(proc->proc_name, vp->vers_num); f_print(fout, "("); if (proc->arg_num < 2) { /* single argument */ if (!streq(proc->args.decls->decl.type, "void")) @@ -379,7 +367,7 @@ write_real_program(definition *def) } static void -write_program(definition *def, char *storage) +write_program(definition *def, const char *storage) { version_list *vp; proc_list *proc; @@ -392,15 +380,8 @@ write_program(definition *def, char *storage) f_print(fout, "void\n"); pvname(def->def_name, vp->vers_num); - if (Cflag) { - f_print(fout, "(struct svc_req *%s, ", RQSTP); - f_print(fout, "register SVCXPRT *%s)\n", TRANSP); - } else { - f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); - f_print(fout, " struct svc_req *%s;\n", RQSTP); - f_print(fout, " register SVCXPRT *%s;\n", TRANSP); - } - + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "SVCXPRT *%s)\n", TRANSP); f_print(fout, "{\n"); filled = 0; @@ -427,10 +408,12 @@ write_program(definition *def, char *storage) if (!filled) f_print(fout, "\t\tint fill;\n"); f_print(fout, "\t} %s;\n", ARG); - + if (mtflag) { f_print(fout, "\tunion {\n"); for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (streq(proc->res_type, "void")) + continue; f_print(fout, "\t\t"); ptype(proc->res_prefix, proc->res_type, 0); pvname(proc->proc_name, vp->vers_num); @@ -443,46 +426,32 @@ write_program(definition *def, char *storage) f_print(fout, "\tchar *%s;\n", RESULT); } - if (Cflag) { - f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", - ARG, RESULT); - if (mtflag) - f_print(fout, - "\tbool_t (*%s)(char *, void *, struct svc_req *);\n", - ROUTINE); - else - f_print(fout, - "\tchar *(*%s)(char *, struct svc_req *);\n", - ROUTINE); - } else { + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT); + if (mtflag) f_print(fout, - "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", - ARG, RESULT); - if (mtflag) - f_print(fout, "\tbool_t (*%s)();\n", ROUTINE); - else - f_print(fout, "\tchar *(*%s)();\n", ROUTINE); - } + "\tbool_t (*%s)(char *, void *, struct svc_req *);\n", + ROUTINE); + else + f_print(fout, + "\tchar *(*%s)(char *, struct svc_req *);\n", + ROUTINE); f_print(fout, "\n"); if (timerflag) { if (mtflag) - f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); + f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n"); f_print(fout, "\t_rpcsvcstate = _SERVING;\n"); if (mtflag) - f_print(fout, "\tmutex_unlock(&_svcstate_lock);\n"); + f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n"); } f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); if (!nullproc(vp->procs)) { f_print(fout, "\tcase NULLPROC:\n"); f_print(fout, - Cflag - ? "\t\t(void) svc_sendreply(%s,\n\t\t\t\ -(xdrproc_t) xdr_void, (char *)NULL);\n" - : "\t\t(void) svc_sendreply(%s, xdr_void,\n\t\t\t\ -(char *)NULL);\n", + "\t\tsvc_sendreply(%s,\n\t\t\t" + "(xdrproc_t) xdr_void, (char *)NULL);\n", TRANSP); print_return("\t\t"); f_print(fout, "\n"); @@ -497,28 +466,18 @@ write_program(definition *def, char *storage) } p_xdrfunc(RESULT, proc->res_type); - if (Cflag) - if (mtflag) - f_print(fout, - "\t\t%s = (bool_t (*) (char *, void *, struct svc_req *))", - ROUTINE); - else - f_print(fout, - "\t\t%s = (char *(*)(char *, struct svc_req *)) ", - ROUTINE); + if (mtflag) + f_print(fout, + "\t\t%s = (bool_t (*) (char *, void *, struct svc_req *))", + ROUTINE); else - if (mtflag) - f_print(fout, "\t\t%s = (bool_t (*)()) ", - ROUTINE); - else - - f_print(fout, "\t\t%s = (char *(*)()) ", - ROUTINE); - if (newstyle) { - /* new style: calls internal routine */ + f_print(fout, + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", + ROUTINE); + if (newstyle) { /* new style: calls internal routine */ f_print(fout, "_"); } - if ((Cflag || mtflag) && !newstyle) + if (!newstyle) pvname_svc(proc->proc_name, vp->vers_num); else pvname(proc->proc_name, vp->vers_num); @@ -530,32 +489,19 @@ write_program(definition *def, char *storage) print_return("\t\t"); f_print(fout, "\t}\n"); - f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", + f_print(fout, "\tmemset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); - if (Cflag) - printif("getargs", TRANSP, "(caddr_t) &", ARG); - else - printif("getargs", TRANSP, "&", ARG); + printif("getargs", TRANSP, "(caddr_t) &", ARG); printerr("decode", TRANSP); print_return("\t\t"); f_print(fout, "\t}\n"); - if (!mtflag) - if (Cflag) - f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n", - RESULT, ROUTINE, ARG, RQSTP); - else - f_print(fout, "\t%s = (*%s)(&%s, %s);\n", - RESULT, ROUTINE, ARG, RQSTP); + if (!mtflag) + f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); else - if (Cflag) - f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n", - RETVAL, ROUTINE, ARG, RESULT, RQSTP); - else - f_print(fout, "\t%s = (bool_t) (*%s)(&%s, &%s, %s);\n", - RETVAL, ROUTINE, ARG, RESULT, RQSTP); - - + f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n", + RETVAL, ROUTINE, ARG, RESULT, RQSTP); if (mtflag) @@ -570,10 +516,7 @@ write_program(definition *def, char *storage) printerr("systemerr", TRANSP); f_print(fout, "\t}\n"); - if (Cflag) - printif("freeargs", TRANSP, "(caddr_t) &", ARG); - else - printif("freeargs", TRANSP, "&", ARG); + printif("freeargs", TRANSP, "(caddr_t) &", ARG); sprintf(_errbuf, "unable to free arguments"); print_err_message("\t\t"); f_print(fout, "\t\texit(1);\n"); @@ -594,15 +537,16 @@ write_program(definition *def, char *storage) } static void -printerr(char *err, char *transp) +printerr(const char *err, const char *transp) { f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp); } static void -printif(char *proc, char *transp, char *prefix, char *arg) +printif(const char *proc, const char *transp, const char *prefix, + const 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); } @@ -617,17 +561,17 @@ nullproc(proc_list *proc) } static void -write_inetmost(char *infile) +write_inetmost(const char *infile) { f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); f_print(fout, "\tint sock;\n"); f_print(fout, "\tint proto;\n"); f_print(fout, "\tstruct sockaddr_in saddr;\n"); - f_print(fout, "\tint asize = sizeof (saddr);\n"); + f_print(fout, "\tsocklen_t asize = sizeof (saddr);\n"); f_print(fout, "\n"); f_print(fout, "\tif (getsockname(0, " "(struct sockaddr *)&saddr, &asize) == 0) {\n"); - f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n\n"); f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); f_print(fout, "\t\t\texit(1);\n"); f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); @@ -645,24 +589,24 @@ write_inetmost(char *infile) } static void -print_return(char *space) +print_return(const char *space) { if (exitnow) f_print(fout, "%sexit(0);\n", space); else { if (timerflag) { if (mtflag) - f_print(fout, "%smutex_lock(&_svcstate_lock);\n", space); + f_print(fout, "%spthread_mutex_lock(&_svcstate_lock);\n", space); f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space); if (mtflag) - f_print(fout, "%smutex_unlock(&_svcstate_lock);\n", space); + f_print(fout, "%spthread_mutex_unlock(&_svcstate_lock);\n", space); } f_print(fout, "%sreturn;\n", space); } } static void -print_pmapunset(char *space) +print_pmapunset(const char *space) { list *l; definition *def; @@ -673,7 +617,7 @@ print_pmapunset(char *space) if (def->def_kind == DEF_PROGRAM) { for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { - f_print(fout, "%s(void) pmap_unset(%s, %s);\n", + f_print(fout, "%spmap_unset(%s, %s);\n", space, def->def_name, vp->vers_name); } } @@ -681,7 +625,7 @@ print_pmapunset(char *space) } static void -print_err_message(char *space) +print_err_message(const char *space) { if (logflag) f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf); @@ -716,13 +660,7 @@ write_msg_out(void) * in the toplevel RPC server code. */ f_print(fout, "static\n"); - - if (!Cflag) { - f_print(fout, "void _msgout(msg)\n"); - f_print(fout, "\tchar *msg;\n"); - } else { - f_print(fout, "void _msgout(char* msg)\n"); - } + f_print(fout, "void _msgout(const char* msg)\n"); f_print(fout, "{\n"); f_print(fout, "#ifdef RPC_SVC_FG\n"); if (inetdflag || pmflag) @@ -730,7 +668,7 @@ write_msg_out(void) f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n"); f_print(fout, "\telse\n"); f_print(fout, - "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n"); + "\t\tfprintf(stderr, \"%%s\\n\", msg);\n"); f_print(fout, "#else\n"); f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n"); f_print(fout, "#endif\n"); @@ -748,15 +686,10 @@ write_timeout_func(void) f_print(fout, "\n"); f_print(fout, "static void\n"); - if (!Cflag) { - f_print(fout, "closedown(sig)\n"); - f_print(fout, "\tint sig;\n"); - } else { - f_print(fout, "closedown(int sig)\n"); - } + f_print(fout, "closedown(int sig)\n"); f_print(fout, "{\n"); if (mtflag) - f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); + f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n"); f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\n"); f_print(fout, "\t\textern fd_set svc_fdset;\n"); f_print(fout, "\t\tstatic int size;\n"); @@ -777,7 +710,7 @@ write_timeout_func(void) f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0) {\n"); if (mtflag) - f_print(fout, "\t\t\t\tmutex_unlock(&_svcstate_lock);\n"); + f_print(fout, "\t\t\t\tpthread_mutex_unlock(&_svcstate_lock);\n"); f_print(fout, "\t\t\t\treturn;\n\t\t\t}\n"); } else { @@ -794,11 +727,10 @@ write_timeout_func(void) f_print(fout, "\tif (_rpcsvcstate == _SERVED)\n"); f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n"); if (mtflag) - f_print(fout, "\tmutex_unlock(&_svcstate_lock);\n"); + f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n"); - f_print(fout, "\t(void) signal(SIGALRM, %s closedown);\n", - Cflag? "(SIG_PF)" : "(void(*)())"); - f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); + f_print(fout, "\tsignal(SIGALRM, closedown);\n"); + f_print(fout, "\talarm(_RPCSVC_CLOSEDOWN/2);\n"); f_print(fout, "}\n"); } @@ -807,15 +739,21 @@ write_timeout_func(void) * Write the most of port monitor support */ static void -write_pm_most(char *infile, int netflag) +write_pm_most(const char *infile, int netflag) { list *l; definition *def; version_list *vp; - f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); - f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); - f_print(fout, " !strcmp(mname, \"timod\"))) {\n"); + if (tirpc_socket) { + f_print(fout, + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n"); + } else { + f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); + f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); + f_print(fout, " !strcmp(mname, \"timod\"))) {\n"); + } f_print(fout, "\t\tchar *netid;\n"); if (!netflag) { /* Not included by -n option */ f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n"); @@ -828,6 +766,14 @@ write_pm_most(char *infile, int netflag) * f_print(fout, "\t\textern char *getenv();\n"); */ f_print(fout, "\n"); + if (tirpc_socket) { + f_print(fout, "\t\tif (saddr.ss_family != AF_INET &&\n"); + f_print(fout, "\t\t saddr.ss_family != AF_INET6)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print(fout, "\t\t\texit(1);\n"); + } f_print(fout, "\t\t_rpcpmstart = 1;\n"); open_log_file(infile, "\t\t"); f_print(fout, "\n\t\tif ((netid = \ @@ -842,27 +788,40 @@ getenv(\"NLSPROVIDER\")) == NULL) {\n"); f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n"); sprintf(_errbuf, "cannot get transport info"); print_err_message("\t\t\t\t"); - if (timerflag) - f_print(fout, "\n\t\t\tpmclose = \ -(t_getstate(0) != T_DATAXFER);\n"); + if (timerflag) { + if (tirpc_socket) + f_print(fout, "\n\t\t\tpmclose = 1;\t/* XXX */\n"); + else + f_print(fout, + "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); + } f_print(fout, "\t\t}\n"); /* * A kludgy support for inetd services. Inetd only works with * sockmod, and RPC works only with timod, hence all this jugglery */ - f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); - f_print(fout, - "\t\t\tif (ioctl(0, I_POP, 0) || \ -ioctl(0, I_PUSH, \"timod\")) {\n"); - sprintf(_errbuf, "could not get the right module"); - print_err_message("\t\t\t\t"); - f_print(fout, "\t\t\t\texit(1);\n"); - f_print(fout, "\t\t\t}\n"); - f_print(fout, "\t\t}\n"); - f_print(fout, - "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) \ -== NULL) {\n", + if (!tirpc_socket) { + f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); + f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || "); + f_print(fout, "ioctl(0, I_PUSH, \"timod\")) {\n"); + sprintf(_errbuf, "could not get the right module"); + print_err_message("\t\t\t\t"); + f_print(fout, "\t\t\t\texit(1);\n"); + f_print(fout, "\t\t\t}\n"); + f_print(fout, "\t\t}\n"); + } + if (tirpcflag) { + f_print(fout, + "\t\tif ((%s = svc_tli_create(0, nconf, NULL, \ + RPC_MAXDATASIZE, RPC_MAXDATASIZE)) \ + == NULL) {\n", TRANSP); + } else { + f_print(fout, + "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) \ + == NULL) {\n", + TRANSP); + } sprintf(_errbuf, "cannot create server handle"); print_err_message("\t\t\t"); f_print(fout, "\t\t\texit(1);\n"); @@ -887,9 +846,8 @@ ioctl(0, I_PUSH, \"timod\")) {\n"); } if (timerflag) { f_print(fout, "\t\tif (pmclose) {\n"); - f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", - Cflag? "(SIG_PF)" : "(void(*)())"); - f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); + f_print(fout, "\t\t\tsignal(SIGALRM, closedown);\n"); + f_print(fout, "\t\t\talarm(_RPCSVC_CLOSEDOWN/2);\n"); f_print(fout, "\t\t}\n"); } f_print(fout, "\t\tsvc_run();\n"); @@ -902,7 +860,7 @@ ioctl(0, I_PUSH, \"timod\")) {\n"); * Support for backgrounding the server if self started. */ static void -write_rpc_svc_fg(char *infile, char *sp) +write_rpc_svc_fg(const char *infile, const char *sp) { f_print(fout, "#ifndef RPC_SVC_FG\n"); f_print(fout, "%sint size;\n", sp); @@ -928,11 +886,11 @@ write_rpc_svc_fg(char *infile, char *sp) } f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp); - f_print(fout, "%s\t(void) close(i);\n", sp); + f_print(fout, "%s\tclose(i);\n", sp); /* Redirect stderr and stdout to console */ f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp); - f_print(fout, "%s(void) dup2(i, 1);\n", sp); - f_print(fout, "%s(void) dup2(i, 2);\n", sp); + f_print(fout, "%sdup2(i, 1);\n", sp); + f_print(fout, "%sdup2(i, 2);\n", sp); /* This removes control of the controlling terminal */ if (tirpcflag) { f_print(fout, "%ssetsid();\n", sp); @@ -940,8 +898,8 @@ write_rpc_svc_fg(char *infile, char *sp) f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp); f_print(fout, "%sif (i >= 0) {\n", sp); f_print(fout, - "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp); - f_print(fout, "%s\t(void) close(i);\n", sp); + "%s\tioctl(i, TIOCNOTTY, (char *)NULL);\n", sp); + f_print(fout, "%s\tclose(i);\n", sp); f_print(fout, "%s}\n", sp); } if (!logflag) @@ -952,7 +910,7 @@ write_rpc_svc_fg(char *infile, char *sp) } static void -open_log_file(char *infile, char *sp) +open_log_file(const char *infile, const char *sp) { char *s; @@ -968,12 +926,12 @@ open_log_file(char *infile, char *sp) * write a registration for the given transport for Inetd */ void -write_inetd_register(char *transp) +write_inetd_register(const char *transp) { list *l; definition *def; version_list *vp; - char *sp; + const char *sp; int isudp; char tmpbuf[32]; diff --git a/usr.bin/rpcgen/rpc_tblout.c b/usr.bin/rpcgen/rpc_tblout.c index 42841993b3..ccbb5e47ba 100644 --- a/usr.bin/rpcgen/rpc_tblout.c +++ b/usr.bin/rpcgen/rpc_tblout.c @@ -5,34 +5,32 @@ * 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 * - * @(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI - * $FreeBSD: src/usr.bin/rpcgen/rpc_tblout.c,v 1.4 1999/08/28 01:05:17 peter Exp $ + * @(#)rpc_tblout.c 1.11 93/07/05 SMI; 1.4 89/02/22 (C) 1988 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_tblout.c,v 1.12 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_tblout.c,v 1.4 2004/06/19 16:40:36 joerg Exp $ */ -#ident "@(#)rpc_tblout.c 1.11 93/07/05 SMI" - /* * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler * Copyright (C) 1989, Sun Microsystems, Inc. @@ -41,6 +39,7 @@ #include #include #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" #define TABSIZE 8 @@ -59,9 +58,8 @@ static char null_entry[] = "\n\t(char *(*)())0,\n\ static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; -extern int nullproc(proc_list *); static void write_table(definition *); -static void printit(char *, char *); +static void printit(const char *, const char *); void write_tables(void) @@ -116,11 +114,11 @@ write_table(definition *def) f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION("); /* routine to invoke */ - if (Cflag && !newstyle) + if(!newstyle) pvname_svc(proc->proc_name, vp->vers_num); else { if (newstyle) - f_print( fout, "_"); /* calls internal func */ + f_print(fout, "_"); /* calls internal func */ pvname(proc->proc_name, vp->vers_num); } f_print(fout, "),\n"); @@ -147,7 +145,7 @@ write_table(definition *def) } static void -printit(char *prefix, char *type) +printit(const char *prefix, const char *type) { int len; int tabs; diff --git a/usr.bin/rpcgen/rpc_util.c b/usr.bin/rpcgen/rpc_util.c index 62c7464fd1..bce553618c 100644 --- a/usr.bin/rpcgen/rpc_util.c +++ b/usr.bin/rpcgen/rpc_util.c @@ -5,34 +5,32 @@ * 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 * - * @(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI - * $FreeBSD: src/usr.bin/rpcgen/rpc_util.c,v 1.6 1999/08/28 01:05:17 peter Exp $ + * @(#)rpc_util.c 1.14 93/07/05 SMI; 1.11 89/02/22 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_util.c,v 1.10 2005/11/13 21:17:24 dwmalone Exp $ * $DragonFly: src/usr.bin/rpcgen/rpc_util.c,v 1.4 2004/06/19 16:40:36 joerg Exp $ */ -#ident "@(#)rpc_util.c 1.14 93/07/05 SMI" - /* * rpc_util.c, Utility routines for the RPC protocol compiler * Copyright (C) 1989, Sun Microsystems, Inc. @@ -42,8 +40,8 @@ #include #include #include -#include "rpc_scan.h" #include "rpc_parse.h" +#include "rpc_scan.h" #include "rpc_util.h" #define ARGEXT "argument" @@ -52,10 +50,10 @@ char curline[MAXLINESIZE]; /* current read line */ char *where = curline; /* current point in line */ int linenum = 0; /* current line number */ -char *infilename; /* input filename */ +const char *infilename; /* input filename */ #define NFILES 7 -char *outfiles[NFILES]; /* output file names */ +const char *outfiles[NFILES]; /* output file names */ int nfiles; FILE *fout; /* file pointer of current output */ @@ -81,7 +79,7 @@ reinitialize(void) * string equality */ int -streq(char *a, char *b) +streq(const char *a, const char *b) { return(strcmp(a, b) == 0); } @@ -90,7 +88,7 @@ streq(char *a, char *b) * find a value in a list */ definition * -findval(list *lst, char *val, int (*cmp) (definition *, char *)) +findval(list *lst, const char *val, int (*cmp)(definition *, const char *)) { for (; lst != NULL; lst = lst->next) { if ((*cmp) (lst->val, val)) @@ -110,20 +108,20 @@ storeval(list **lstp, definition *val) for (l = lstp; *l != NULL; l = (list **) & (*l)->next) ; - lst = ALLOC(list); + lst = XALLOC(list); lst->val = val; lst->next = NULL; *l = lst; } static int -findit(definition *def, char *type) +findit(definition *def, const char *type) { return(streq(def->def_name, type)); } -static char * -fixit(char *type, char *orig) +static const char * +fixit(const char *type, const char *orig) { definition *def; @@ -144,14 +142,14 @@ fixit(char *type, char *orig) } } -char * -fixtype(char *type) +const char * +fixtype(const char *type) { return(fixit(type, type)); } -char * -stringfix(char *type) +const char * +stringfix(const char *type) { if (streq(type, "string")) return("wrapstring"); @@ -160,7 +158,7 @@ stringfix(char *type) } void -ptype(char *prefix, char *type, int follow) +ptype(const char *prefix, const char *type, int follow) { if (prefix != NULL) { if (streq(prefix, "enum")) @@ -177,7 +175,7 @@ ptype(char *prefix, char *type, int follow) } static int -typedefed(definition *def, char *type) +typedefed(definition *def, const char *type) { if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) return(0); @@ -186,7 +184,7 @@ typedefed(definition *def, char *type) } int -isvectordef(char *type, relation rel) +isvectordef(const char *type, relation rel) { definition *def; @@ -212,7 +210,7 @@ isvectordef(char *type, relation rel) } char * -locase(char *str) +locase(const char *str) { char c; static char buf[100]; @@ -225,13 +223,13 @@ locase(char *str) } void -pvname_svc(char *pname, char *vnum) +pvname_svc(const char *pname, const char *vnum) { f_print(fout, "%s_%s_svc", locase(pname), vnum); } void -pvname(char *pname, char *vnum) +pvname(const char *pname, const char *vnum) { f_print(fout, "%s_%s", locase(pname), vnum); } @@ -240,7 +238,7 @@ pvname(char *pname, char *vnum) * print a useful (?) error message, and then die */ void -error(char *msg) +error(const char *msg) { printwhere(); warnx("%s, line %d: %s", infilename, linenum, msg); @@ -262,7 +260,7 @@ crash(void) } void -record_open(char *file) +record_open(const char *file) { if (nfiles < NFILES) { outfiles[nfiles++] = file; @@ -273,7 +271,7 @@ record_open(char *file) } static char expectbuf[100]; -static char *toktostr(); +static const char *toktostr(tok_kind); /* * error, token encountered was not the expected one @@ -352,7 +350,7 @@ static token tokstrings[] = { {TOK_EOF, "??????"} }; -static char * +static const char * toktostr(tok_kind kind) { token *sp; @@ -405,13 +403,11 @@ printwhere(void) } char * -make_argname(char *pname, char *vname) +make_argname(const char *pname, const char *vname) { char *name; - name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); - if (!name) - errx(1, "failed in malloc"); + name = xmalloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT); return(name); } @@ -420,12 +416,11 @@ bas_type *typ_list_h; bas_type *typ_list_t; void -add_type(int len, char *type) +add_type(int len, const char *type) { bas_type *ptr; - if ((ptr = (bas_type *) malloc(sizeof (bas_type))) == NULL) - errx(1, "failed in malloc"); + ptr = XALLOC(bas_type); ptr->name = type; ptr->length = len; @@ -441,7 +436,7 @@ add_type(int len, char *type) bas_type * -find_type(char *type) +find_type(const char *type) { bas_type * ptr; @@ -455,3 +450,39 @@ find_type(char *type) } return(NULL); } + +void * +xmalloc(size_t size) +{ + void *p; + + if ((p = malloc(size)) == NULL) { + warnx("malloc failed"); + crash(); + } + return (p); +} + +void * +xrealloc(void *ptr, size_t size) +{ + void *p; + + if ((p = realloc(ptr, size)) == NULL) { + warnx("realloc failed"); + crash(); + } + return (p); +} + +char * +xstrdup(const char *str) +{ + char *p; + + if ((p = strdup(str)) == NULL) { + warnx("strdup failed"); + crash(); + } + return (p); +} diff --git a/usr.bin/rpcgen/rpc_util.h b/usr.bin/rpcgen/rpc_util.h index d56e5c040a..97cf03be67 100644 --- a/usr.bin/rpcgen/rpc_util.h +++ b/usr.bin/rpcgen/rpc_util.h @@ -5,28 +5,31 @@ * 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 + * + * @(#)rpc_util.h 1.16 94/05/15 SMI; 1.5 90/08/29 (C) 1987 SMI + * $FreeBSD: src/usr.bin/rpcgen/rpc_util.h,v 1.12 2005/11/13 21:17:24 dwmalone Exp $ + * $DragonFly: src/usr.bin/rpcgen/rpc_util.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ -#pragma ident "@(#)rpc_util.h 1.16 94/05/15 SMI" /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ @@ -47,29 +50,23 @@ * * * -* Copyright Notice +* Copyright Notice * -* Notice of copyright on this source code product does not indicate +* Notice of copyright on this source code product does not indicate * publication. * * (c) 1986,1987,1988.1989 Sun Microsystems, Inc * (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. * All rights reserved. -*/ - -/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */ -/* $DragonFly: src/usr.bin/rpcgen/rpc_util.h,v 1.2 2004/06/19 16:40:36 joerg Exp $ */ +*/ /* - * rpc_util.h, Useful definitions for the RPC protocol compiler + * rpc_util.h, Useful definitions for the RPC protocol compiler */ #include #include -#include "rpc_scan.h" - -#define alloc(size) malloc((unsigned)(size)) -#define ALLOC(object) (object *) malloc(sizeof(object)) +#define XALLOC(object) (object *) xmalloc(sizeof(object)) #define s_print (void) sprintf #define f_print (void) fprintf @@ -81,7 +78,7 @@ struct list { typedef struct list list; struct xdrfunc { - char *name; + const char *name; int pointerp; struct xdrfunc *next; }; @@ -98,22 +95,23 @@ struct commandline { int Ssflag; /* produce server sample code */ int Scflag; /* produce client sample code */ int makefileflag; /* Generate a template Makefile */ - char *infile; /* input module name */ - char *outfile; /* output module name */ + const char *infile; /* input module name */ + const char *outfile; /* output module name */ }; #define PUT 1 #define GET 2 /* - * Global variables + * Global variables */ #define MAXLINESIZE 1024 extern char curline[MAXLINESIZE]; extern char *where; extern int linenum; +extern int tirpc_socket; -extern char *infilename; +extern const char *infilename; extern FILE *fout; extern FILE *fin; @@ -128,14 +126,13 @@ extern xdrfunc *xdrfunc_head, *xdrfunc_tail; * All the option flags */ extern int inetdflag; -extern int pmflag; +extern int pmflag; extern int tblflag; extern int logflag; extern int newstyle; -extern int Cflag; /* ANSI-C/C++ flag */ extern int CCflag; /* C++ flag */ extern int tirpcflag; /* flag for generating tirpc code */ -extern int rpcgen_inline; /* if this is 0, then do not generate inline code */ +extern int inline_size; /* if this is 0, then do not generate inline code */ extern int mtflag; /* @@ -150,66 +147,82 @@ extern int nonfatalerrors; extern pid_t childpid; /* - * rpc_util routines + * rpc_util routines */ void reinitialize(void); -void crash(void ); -void add_type(int len, char *type); - +void crash(void); +void add_type(int, const char *); void storeval(list **, definition *); +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *); +char *make_argname(const char *, const char *); #define STOREVAL(list,item) \ storeval(list,item) -definition *findval(list *, char *, int (*)(definition *, char *)); +definition *findval(list *, const char *, int (*)(definition *, const char *)); #define FINDVAL(list,item,finder) \ findval(list, item, finder) -char *fixtype(char *); -char *stringfix(char *); -char *locase(char *); -void pvname_svc(char *, char *); -void pvname(char *, char *); -void ptype(char *, char *, int); -int isvectordef(char *, relation); -int streq(char *, char *); -void error(char *); +const char *fixtype(const char *); +const char *stringfix(const char *); +char *locase(const char *); +void pvname_svc(const char *, const char *); +void pvname(const char *, const char *); +void ptype(const char *, const char *, int); +int isvectordef(const char *, relation); +int streq(const char *, const char *); +void error(const char *); void expected1(tok_kind); void expected2(tok_kind, tok_kind); void expected3(tok_kind, tok_kind, tok_kind); void tabify(FILE *, int); -void record_open(char *); -bas_type *find_type(char *); +void record_open(const char *); +bas_type *find_type(const char *); + /* - * rpc_cout routines + * rpc_cout routines */ -void cprint(void); void emit(definition *); /* - * rpc_hout routines + * rpc_hout routines */ -void print_datadef(definition *); -void print_funcdef(definition *); -void print_xdr_func_def(char *, int, int); +void pdeclaration(const char *, declaration *, int, const char *); +void print_datadef(definition *, int); +void print_funcdef(definition *, int); +void print_xdr_func_def(const char *, int); /* - * rpc_svcout routines + * rpc_svcout routines */ -void write_most(char *, int, int); +void write_most(const char *, int, int); void write_rest(void); -void write_programs(char *); +void write_programs(const char *); void write_svc_aux(int); -void write_inetd_register(char *); -void write_netid_register(char *); -void write_nettype_register(char *); +void write_inetd_register(const char *); +void write_netid_register(const char *); +void write_nettype_register(const char *); +int nullproc(proc_list *); + /* * rpc_clntout routines */ void write_stubs(void); +void printarglist(proc_list *, const char *, const char *, + const char *); /* * rpc_tblout routines */ void write_tables(void); + +/* + * rpc_sample routines + */ +void write_sample_svc(definition *); +int write_sample_clnt(definition *); +void write_sample_clnt_main(void); +void add_sample_msg(void); diff --git a/usr.bin/rpcgen/rpcgen.1 b/usr.bin/rpcgen/rpcgen.1 index 25d59f216e..0c194032bf 100644 --- a/usr.bin/rpcgen/rpcgen.1 +++ b/usr.bin/rpcgen/rpcgen.1 @@ -1,8 +1,9 @@ .\" @(#)rpcgen.1 1.35 93/06/02 SMI -.\" $FreeBSD: src/usr.bin/rpcgen/rpcgen.1,v 1.12.2.4 2002/06/21 15:28:50 charnier Exp $ +.\" $FreeBSD: src/usr.bin/rpcgen/rpcgen.1,v 1.24 2005/09/02 18:37:34 stefanf Exp $ .\" $DragonFly: src/usr.bin/rpcgen/rpcgen.1,v 1.4 2008/04/16 07:21:57 swildner Exp $ .\" Copyright 1985-1993 Sun Microsystems, Inc. -.Dd March 28, 1993 +.\" +.Dd September 2, 2005 .Dt RPCGEN 1 .Os .Sh NAME @@ -19,7 +20,7 @@ .Fl D Ns Ar name Ns Op Ar =value .Oc .Op Fl i Ar size -.Op Fl I Op Fl K Ar seconds +.Op Fl I Fl P Op Fl K Ar seconds .Op Fl L .Op Fl M .Op Fl N @@ -112,7 +113,10 @@ the server side sample file to and the sample makefile to .Pa makefile.proto . .Pp -The server created can be started both by the port monitors +If option +.Fl I +is set, +the server created can be started both by the port monitors (for example, .Xr inetd 8 ) or by itself. @@ -121,9 +125,9 @@ it creates servers only for the transport for which the file descriptor .Em 0 was passed. -The name of the transport must be specified +The name of the transport may be specified by setting up the environment variable -.Ev PM_TRANSPORT . +.Ev NLSPROVIDER . When the server generated by .Nm is executed, @@ -250,24 +254,13 @@ Generate transport specific .Tn RPC code for older versions of the operating system. -.Pp -Note: in -.Dx , -this compatibility flag is turned on by -default since -.Dx -supports only the older -.Tn ONC RPC -library. .It Fl c Compile into .Tn XDR routines. .It Fl C -Generate header and stub files which can be used with -.Tn ANSI -C compilers. Headers generated with this flag can also be -used with C++ programs. +Generate ANSI C code. +This is always done, the flag is only provided for backwards compatibility. .It Fl D Ns Ar name .It Fl D Ns Ar name=value .\".It Fl D Ns Ar name Ns Op Ar =value @@ -300,14 +293,15 @@ Note: in order to provide backwards compatibility with the older on the .Dx platform, the default is actually 0 (which means -that inline code generation is disabled by default). You must specify +that inline code generation is disabled by default). +You must specify a non-zero value explicitly to override this default. .It Fl I Compile support for .Xr inetd 8 in the server side stubs. Such servers can be self-started or can be started by -.Nm inetd . +.Xr inetd 8 . When the server is self-started, it backgrounds itself by default. A special define symbol .Em RPC_SVC_FG @@ -318,22 +312,23 @@ the option. .Pp If there are no pending client requests, the -.Nm inetd +.Xr inetd 8 servers exit after 120 seconds (default). The default can be changed with the .Fl K option. All the error messages for -.Nm inetd +.Xr inetd 8 servers are always logged with .Xr syslog 3 . -.\" .IP -.\" Note: -.\" this option is supported for backward compatibility only. -.\" By default, -.\" .B rpcgen -.\" generates servers that can be invoked through portmonitors. +.Pp +Note: +Contrary to some systems, in +.Dx +this option is needed to generate +servers that can be invoked through portmonitors and +.Xr inetd 8 . .Pp .It Fl K Ar seconds By default, services created using @@ -348,7 +343,7 @@ To create a server that exits immediately upon servicing a request, use .Fl K Ar 0 . To create a server that never exits, the appropriate argument is -.Fl k Ar -1 . +.Fl K Ar -1 . .Pp When monitoring for a server, some portmonitors @@ -386,7 +381,7 @@ However, the functions are not yet MT-safe, which means that rpcgen generated server-side code will not be MT-safe. .It Fl N -This option allows procedures to have multiple arguments. +Allow procedures to have multiple arguments. It also uses the style of parameter passing that closely resembles C. So, when passing an argument to a remote procedure, you do not have to pass a pointer to the argument, but can pass the argument itself. @@ -421,6 +416,22 @@ standard output is used and .Fl t modes only). +.It Fl P +Compile support for +port monitors +in the server side stubs. +.Pp +Note: +Contrary to some systems, in +.Dx +this option is needed to generate +servers that can be monitored. +.Pp +If the +.Fl I +option has been specified, +.Fl P +is turned off automatically. .It Fl s Ar nettype Compile into server-side stubs for all the transports belonging to the class @@ -513,9 +524,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 6e71f64d15..411cfbe9a8 100644 --- a/usr.bin/rpcinfo/Makefile +++ b/usr.bin/rpcinfo/Makefile @@ -1,9 +1,11 @@ # from: @(#)Makefile 5.2 (Berkeley) 5/11/90 -# $FreeBSD: src/usr.bin/rpcinfo/Makefile,v 1.4.2.1 2001/04/25 11:29:36 ru Exp $ +# $FreeBSD: src/usr.bin/rpcinfo/Makefile,v 1.8 2006/07/27 13:47:02 yar Exp $ # $DragonFly: src/usr.bin/rpcinfo/Makefile,v 1.3 2007/08/27 16:50:58 pavalos Exp $ PROG= rpcinfo MAN= rpcinfo.8 -WARNS?= 0 + +CFLAGS+= -DPORTMAP +WARNS?= 2 .include diff --git a/usr.bin/rpcinfo/rpcinfo.8 b/usr.bin/rpcinfo/rpcinfo.8 index 019172fee6..5a1fdfd82e 100644 --- a/usr.bin/rpcinfo/rpcinfo.8 +++ b/usr.bin/rpcinfo/rpcinfo.8 @@ -1,8 +1,11 @@ -.\" from: @(#)rpcinfo.8c 2.2 88/08/03 4.0 RPCSRC; from 1.24 88/02/25 SMI -.\" $FreeBSD: src/usr.bin/rpcinfo/rpcinfo.8,v 1.5.2.2 2002/06/21 15:28:53 charnier Exp $ +.\" @(#)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: src/usr.bin/rpcinfo/rpcinfo.8,v 1.9 2002/10/16 15:38:28 charnier Exp $ .\" $DragonFly: src/usr.bin/rpcinfo/rpcinfo.8,v 1.3 2005/08/01 01:49:18 swildner Exp $ .\" -.Dd December 17, 1987 +.Dd August 18, 1992 .Dt RPCINFO 8 .Os .Sh NAME @@ -10,159 +13,331 @@ .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 The .Nm -utility makes an -.Tn RPC -call to an -.Tn RPC +utility 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 e3a31f71c9..00efc8fd03 100644 --- a/usr.bin/rpcinfo/rpcinfo.c +++ b/usr.bin/rpcinfo/rpcinfo.c @@ -1,15 +1,3 @@ -/* - * Copyright (C) 1986, Sun Microsystems, Inc. - * - * @(#)rpcinfo.c 1.22 87/08/12 SMI - * @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC - * $FreeBSD: src/usr.bin/rpcinfo/rpcinfo.c,v 1.9.2.1 2001/03/04 09:00:23 kris Exp $ - * $DragonFly: src/usr.bin/rpcinfo/rpcinfo.c,v 1.3 2007/11/25 01:28:23 swildner Exp $ - */ -/* - * rpcinfo: ping a particular rpc program - * or dump the portmapper - */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for @@ -38,40 +26,63 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * @(#)rpcinfo.c 1.18 93/07/05 SMI; 1.16 89/04/05 Copyr 1986 Sun Micro + * $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $ + * $FreeBSD: src/usr.bin/rpcinfo/rpcinfo.c,v 1.17 2004/03/11 10:22:25 bde Exp $ + * $DragonFly: src/usr.bin/rpcinfo/rpcinfo.c,v 1.3 2007/11/25 01:28:23 swildner Exp $ */ -#include -#include +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * 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 +#include +#include +#include #include #include +#include +#include +#include +#include #include #include -#include +#include +#include +#include + +#ifdef PORTMAP /* Support for version 2 portmapper */ +#include #include +#include #include #include -#include -#include -#include -#include -#include +#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. @@ -80,25 +91,88 @@ 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(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { - register int c; + 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; @@ -120,15 +194,24 @@ main(argc, argv) function = UDPPING; break; - case 'b': + case 'n': + portnum = (u_short) strtol(optarg, &strptr, 10); + if (strptr == optarg || *strptr != '\0') + errx(1, "%s is illegal port number", optarg); + 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': @@ -138,396 +221,314 @@ 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); + + if (function == NONE) { + if (argc - optind > 1) + function = PROGPING; + else + function = RPCBDUMP; } switch (function) { - +#ifdef PORTMAP case PMAPDUMP: - if (portnum != 0) { + if (portnum != 0) usage(); - return (1); - } pmapdump(argc - optind, argv + optind); 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; + void *localhandle; + struct netconfig *nconf; + CLIENT *clnt; - if (argc < 2 || argc > 3) { - usage(); - exit(1); + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; } - 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); + if (nconf == NULL) { + warnx("getnetconfig: %s", nc_sperror()); + return (NULL); } - 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); + + clnt = clnt_tp_create(NULL, prog, vers, nconf); + endnetconfig(localhandle); + return clnt; +} + +#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; + 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 == 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) { + 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, + NULL, (xdrproc_t) xdr_void, 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); + CLNT_DESTROY(client); + return; + } + /* Version number not known */ + CLNT_CONTROL(client, CLSET_FD_NCLOSE, 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. + */ + 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, + NULL, (xdrproc_t) xdr_void, 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); + 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 { + pstatus(client, prognum, (u_long)0); + exit(1); } - else { - vers = getvers(argv[2]); + 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, + NULL, (xdrproc_t) xdr_void, NULL, to); if (pstatus(client, prognum, vers) < 0) - failure = 1; + failure = 1; + CLNT_DESTROY(client); } if (failure) exit(1); + 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; + CLIENT *client; struct rpcent *rpc; + enum clnt_stat clnt_st; + struct rpc_err err; + char *host; - if (argc > 1) { + if (argc > 1) usage(); + 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 (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) { - 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"); + + 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) + warnx( + "%s does not support portmapper. Try rpcinfo %s instead", + 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", "local"); 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); @@ -537,6 +538,37 @@ pmapdump(argc, argv) } } +static void +get_inet_address(struct sockaddr_in *addr, char *host) +{ + struct netconfig *nconf; + struct addrinfo hints, *res; + int error; + + 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) + errx(1, "couldn't find a suitable transport"); + else { + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; + if ((error = getaddrinfo(host, "rpcbind", &hints, &res)) + != 0) + errx(1, "%s: %s", host, gai_strerror(error)); + else { + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + } + 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 @@ -545,115 +577,1076 @@ 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(&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; - if (argc != 2) { + if (argc != 2) usage(); - exit(1); - } 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); - if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { - fprintf(stderr, "rpcinfo: broadcast failed: %s\n", - clnt_sperrno(rpc_stat)); - exit(1); - } + rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, + (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_void, + NULL, (resultproc_t) reply_proc, NULL); + if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) + errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat)); exit(0); } -static void -deletereg(argc, argv) - int argc; - char **argv; -{ u_long prog_num, version_num ; +static bool_t +add_version(struct rpcbdump_short *rs, u_long vers) +{ + struct verslist *vl; - 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]) ; + 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 void -usage() +static bool_t +add_netid(struct rpcbdump_short *rs, char *netid) { - 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"); + 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 u_long -getprognum(arg) - char *arg; +static void +rpcbdump(int dumptype, char *netid, int argc, char **argv) { - register struct rpcent *rpc; - register u_long prognum; - - if (isalpha(*arg)) { - rpc = getrpcbyname(arg); - if (rpc == NULL) + rpcblist_ptr head = NULL; + struct timeval minutetimeout; + 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(); + 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) + freenetconfigent(nconf); + } + } else + client = local_rpcb(PMAPPROG, RPCBVERS); + + if (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] = '\0'; + 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: warnx("no memory"); + return; +} + +static char nullstring[] = "\000"; + +static void +rpcbaddrlist(char *netid, int argc, char **argv) +{ + rpcb_entry_list_ptr head = NULL; + struct timeval minutetimeout; + CLIENT *client; + struct rpcent *rpc; + char *host; + RPCB parms; + struct netbuf *targaddr; + + if (argc != 3) + usage(); + 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) + freenetconfigent(nconf); + } + if (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; + 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 == 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(); + if (netid) { + nconf = getnetconfigent(netid); + if (nconf == NULL) + errx(1, "netid %s not supported", netid); + } + if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0) + errx(1, + "could not delete registration for prog %s version %s", + argv[0], argv[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, "no address for client handle"); + } + client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0); + if (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(); + nconf = getnetconfigent(netid); + if (nconf == NULL) + errx(1, "could not find %s", netid); + 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, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (argc == 2) { + /* Version number was known */ + if (pstatus(client, prognum, versnum) < 0) + failure = 1; + CLNT_DESTROY(client); + if (failure) + exit(1); + return; + } + /* Version number not known */ + CLNT_CONTROL(client, CLSET_FD_NCLOSE, NULL); + 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. + */ + CLNT_DESTROY(client); + client = clnt_addr_create(address, nconf, prognum, MAX_VERS); + rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, 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 { + pstatus(client, prognum, MAX_VERS); + exit(1); + } + } else { + pstatus(client, prognum, (u_long)0); + exit(1); + } + 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, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (pstatus(client, prognum, versnum) < 0) + failure = 1; + CLNT_DESTROY(client); + } + 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(); + 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 == NULL) + errx(1, "could not find %s", netid); + client = clnt_tp_create(argv[0], prognum, versnum, nconf); + } else { + client = clnt_create(argv[0], prognum, versnum, "NETPATH"); + } + if (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, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (argc == 3) { + /* Version number was known */ + if (pstatus(client, prognum, versnum) < 0) + failure = 1; + 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; + CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); + rpc_stat = CLNT_CALL(client, NULLPROC, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, 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 { + pstatus(client, prognum, MAX_VERS); + exit(1); + } + } else { + pstatus(client, prognum, (u_long)0); + exit(1); + } + for (versnum = minvers; versnum <= maxvers; versnum++) { + CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum); + rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void, + NULL, (xdrproc_t) xdr_void, NULL, to); + if (pstatus(client, prognum, versnum) < 0) + failure = 1; + } + CLNT_DESTROY(client); + if (failure) + exit(1); + return; +} + +static void +usage(void) +{ + 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"); + exit(1); +} + +static u_long +getprognum(char *arg) +{ + char *strptr; + struct rpcent *rpc; + u_long prognum; + char *tptr = arg; + + while (*tptr && isdigit(*tptr++)); + if (*tptr || isalpha(*(tptr - 1))) { + rpc = getrpcbyname(arg); + if (rpc == NULL) errx(1, "%s is unknown service", arg); prognum = rpc->r_number; } else { - prognum = (u_long) atoi(arg); + prognum = strtol(arg, &strptr, 10); + if (strptr == arg || *strptr != '\0') + errx(1, "%s is illegal program number", arg); } - return (prognum); } static u_long -getvers(arg) - char *arg; +getvers(char *arg) { - register u_long vers; + char *strptr; + u_long vers; - vers = (int) atoi(arg); + vers = (int) strtol(arg, &strptr, 10); + if (strptr == arg || *strptr != '\0') + errx(1, "%s is illegal version number", arg); 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(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 == 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; + 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; + 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.1 b/usr.bin/rup/rup.1 index a864d176a2..3f91345596 100644 --- a/usr.bin/rup/rup.1 +++ b/usr.bin/rup/rup.1 @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.bin/rup/rup.1,v 1.7.2.7 2002/06/21 15:29:00 charnier Exp $ +.\" $FreeBSD: src/usr.bin/rup/rup.1,v 1.20 2007/02/28 10:22:19 ru Exp $ .\" $DragonFly: src/usr.bin/rup/rup.1,v 1.2 2003/06/17 04:29:31 dillon Exp $ .\" .Dd June 7, 1993 @@ -62,7 +62,7 @@ work. The .Nm utility uses an RPC protocol defined in -.Pa /usr/include/rpcsvc/rstat.x . +.In rpcsvc/rstat.x . .Sh EXAMPLES .Bd -literal example% rup otherhost @@ -76,23 +76,25 @@ The .Xr rpc.rstatd 8 daemon has not been started on the remote host. .It rup: RPC: Timed out -A communication error occurred. Either the network is +A communication error occurred. +Either the network is excessively congested, or the .Xr rpc.rstatd 8 daemon has terminated on the remote host. .It rup: RPC: Port mapper failure - RPC: Timed out The remote host is not running the portmapper (see -.Xr portmap 8 ) , -and cannot accommodate any RPC-based services. The host may be down. +.Xr rpcbind 8 ) , +and cannot accommodate any RPC-based services. +The host may be down. .El .Sh SEE ALSO -.Xr portmap 8 , +.Xr rpcbind 8 , .Xr rpc.rstatd 8 .Sh HISTORY The .Nm command appeared in -.Em Sun-OS . +.Tn Sun-OS . .Sh BUGS The sorting options are not implemented. diff --git a/usr.bin/rup/rup.c b/usr.bin/rup/rup.c index 9d310adf3f..93a7725cbb 100644 --- a/usr.bin/rup/rup.c +++ b/usr.bin/rup/rup.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.bin/rup/rup.c,v 1.11.2.2 2001/07/02 23:43:04 mikeh Exp $ + * $FreeBSD: src/usr.bin/rup/rup.c,v 1.19 2005/12/04 18:25:26 philip Exp $ * $DragonFly: src/usr.bin/rup/rup.c,v 1.5 2005/08/04 18:21:25 liamfoy Exp $ */ #include @@ -85,8 +85,8 @@ remember_host(struct in_addr addr) hosts = hp; } -static int -rstat_reply(char *replyp, struct sockaddr_in *raddrp) +static bool_t +rstat_reply(caddr_t replyp, struct sockaddr_in *raddrp) { struct tm *tmp_time; struct tm host_time; @@ -96,6 +96,7 @@ rstat_reply(char *replyp, struct sockaddr_in *raddrp) struct hostent *hp; char *host; statstime *host_stat = (statstime *)replyp; + time_t tmp_time_t; if (search_host(raddrp->sin_addr)) return(0); @@ -113,13 +114,26 @@ rstat_reply(char *replyp, struct sockaddr_in *raddrp) printf("%-*s\t", HOST_WIDTH, host); - tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec); - host_time = *tmp_time; + if (sizeof(time_t) == sizeof(host_stat->curtime.tv_sec)) { + tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec); + host_time = *tmp_time; + + host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; - host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; + tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec); + host_uptime = *tmp_time; + } + else { /* non-32-bit time_t */ + tmp_time_t = host_stat->curtime.tv_sec; + tmp_time = localtime(&tmp_time_t); + host_time = *tmp_time; - tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec); - host_uptime = *tmp_time; + host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; + + tmp_time_t = host_stat->curtime.tv_sec; + tmp_time = gmtime(&tmp_time_t); + host_uptime = *tmp_time; + } #define updays (host_stat->curtime.tv_sec / 86400) if (host_uptime.tm_yday != 0) @@ -178,14 +192,15 @@ onehost(const char *host) bzero(&host_stat, sizeof(host_stat)); tv.tv_sec = 15; /* XXX ??? */ tv.tv_usec = 0; - if (clnt_call(rstat_clnt, RSTATPROC_STATS, xdr_void, NULL, (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) { + if (clnt_call(rstat_clnt, RSTATPROC_STATS, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) { clnt_perror(rstat_clnt, host); clnt_destroy(rstat_clnt); return(1); } addr.sin_addr.s_addr = *(int *)hp->h_addr; - rstat_reply((char *)&host_stat, &addr); + rstat_reply((caddr_t)&host_stat, &addr); clnt_destroy(rstat_clnt); return (0); } @@ -197,8 +212,9 @@ allhosts(void) enum clnt_stat clnt_stat; clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, - xdr_void, NULL, - (xdrproc_t)xdr_statstime, (char *)&host_stat, rstat_reply); + (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_statstime, &host_stat, + (resultproc_t)rstat_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } @@ -206,7 +222,7 @@ allhosts(void) static void usage(void) { - fprintf(stderr, "usage: rup [hosts ...]\n"); + fprintf(stderr, "usage: rup [host ...]\n"); exit(1); } diff --git a/usr.bin/rusers/Makefile b/usr.bin/rusers/Makefile index 7c33189e83..9e317fa487 100644 --- a/usr.bin/rusers/Makefile +++ b/usr.bin/rusers/Makefile @@ -5,6 +5,5 @@ PROG = rusers DPADD= ${LIBRPCSVC} LDADD= -lrpcsvc -WARNS?= 1 .include diff --git a/usr.bin/rusers/rusers.1 b/usr.bin/rusers/rusers.1 index 0bd4ff4f0a..7f29141302 100644 --- a/usr.bin/rusers/rusers.1 +++ b/usr.bin/rusers/rusers.1 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)rusers.1 6.7 (Berkeley) 4/23/91 -.\" $FreeBSD: src/usr.bin/rusers/rusers.1,v 1.8.2.5 2001/08/16 13:17:02 ru Exp $ +.\" $FreeBSD: src/usr.bin/rusers/rusers.1,v 1.18 2004/07/04 20:55:50 ru Exp $ .\" $DragonFly: src/usr.bin/rusers/rusers.1,v 1.3 2004/07/17 21:06:38 hmp Exp $ .\" .Dd April 23, 1991 @@ -89,7 +89,7 @@ excessively congested, or the daemon has terminated on the remote host. .It rusers: "RPC: Port mapper failure - RPC: Timed out" The remote host is not running the portmapper (see -.Xr portmap 8 ) , +.Xr rpcbind 8 ) , and cannot accommodate any RPC-based services. The host may be down. .El @@ -97,7 +97,7 @@ The host may be down. .Xr rwho 1 , .Xr users 1 , .Xr who 1 , -.Xr portmap 8 , +.Xr rpcbind 8 , .Xr rpc.rusersd 8 .Sh HISTORY The diff --git a/usr.bin/rusers/rusers.c b/usr.bin/rusers/rusers.c index 07ea2bb24f..ca63543707 100644 --- a/usr.bin/rusers/rusers.c +++ b/usr.bin/rusers/rusers.c @@ -30,21 +30,24 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.bin/rusers/rusers.c,v 1.8.2.1 2001/07/02 23:43:05 mikeh Exp $ + * $FreeBSD: src/usr.bin/rusers/rusers.c,v 1.17 2005/05/21 09:55:08 ru Exp $ * $DragonFly: src/usr.bin/rusers/rusers.c,v 1.4 2008/10/16 01:52:33 swildner Exp $ */ #include #include + #include #include #include + #include + #include #include #include #include -#include +#include #include #define MAX_INT 0x7fffffff @@ -59,7 +62,7 @@ struct host_list { struct in_addr addr; } *hosts; -int +static int search_host(struct in_addr addr) { struct host_list *hp; @@ -74,7 +77,7 @@ search_host(struct in_addr addr) return (0); } -void +static void remember_host(struct in_addr addr) { struct host_list *hp; @@ -86,16 +89,19 @@ remember_host(struct in_addr addr) hosts = hp; } -int -rusers_reply(char *replyp, struct sockaddr_in *raddrp) +static int +rusers_reply(caddr_t replyp, struct sockaddr_in *raddrp) { - int x, idle; + u_int x; + int idle; char date[32], idle_time[64], remote[64]; struct hostent *hp; - utmpidlearr *up, u; + utmpidlearr *up, u; char *host; int days, hours, minutes, seconds; + up = &u; + memcpy(up, replyp, sizeof(*up)); if (search_host(raddrp->sin_addr)) return (0); @@ -164,7 +170,7 @@ rusers_reply(char *replyp, struct sockaddr_in *raddrp) return (0); } -void +static void onehost(char *host) { utmpidlearr up; @@ -184,15 +190,15 @@ onehost(char *host) bzero((char *)&up, sizeof(up)); tv.tv_sec = 15; /* XXX ?? */ tv.tv_usec = 0; - if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL, - xdr_utmpidlearr, &up, tv) != RPC_SUCCESS) + if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS) errx(1, "%s", clnt_sperror(rusers_clnt, "")); - memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr)); - rusers_reply((char *)&up, &addr); + memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr)); + rusers_reply((caddr_t)&up, &addr); clnt_destroy(rusers_clnt); } -void +static void allhosts(void) { utmpidlearr up; @@ -200,8 +206,9 @@ allhosts(void) bzero((char *)&up, sizeof(up)); clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, - RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr, (char *)&up, - rusers_reply); + RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_utmpidlearr, (char *)&up, + (resultproc_t)rusers_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } @@ -210,7 +217,7 @@ static void usage(void) { - fprintf(stderr, "usage: rusers [-la] [hosts ...]\n"); + fprintf(stderr, "usage: rusers [-al] [host ...]\n"); exit(1); } @@ -237,7 +244,7 @@ main(int argc, char *argv[]) allhosts(); else { for (; optind < argc; optind++) - (void)onehost(argv[optind]); + onehost(argv[optind]); } exit(0); } diff --git a/usr.bin/rwall/rwall.1 b/usr.bin/rwall/rwall.1 index fe5080cf65..69be809387 100644 --- a/usr.bin/rwall/rwall.1 +++ b/usr.bin/rwall/rwall.1 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)rwall.1 6.7 (Berkeley) 4/23/91 -.\" $FreeBSD: src/usr.bin/rwall/rwall.1,v 1.7.2.4 2001/08/16 13:17:02 ru Exp $ +.\" $FreeBSD: src/usr.bin/rwall/rwall.1,v 1.15 2004/07/04 20:55:50 ru Exp $ .\" $DragonFly: src/usr.bin/rwall/rwall.1,v 1.3 2007/05/13 18:33:59 swildner Exp $ .\" .Dd April 23, 1991 @@ -59,18 +59,20 @@ The .Xr rpc.rwalld 8 daemon has not been started on the remote host. .It rwall: RPC: Timed out -A communication error occurred. Either the network is +A communication error occurred. +Either the network is excessively congested, or the .Xr rpc.rwalld 8 daemon has terminated on the remote host. .It rwall: RPC: Port mapper failure - RPC: Timed out The remote host is not running the portmapper (see -.Xr portmap 8 ) , -and cannot accommodate any RPC-based services. The host may be down. +.Xr rpcbind 8 ) , +and cannot accommodate any RPC-based services. +The host may be down. .El .Sh SEE ALSO .Xr who 1 , -.Xr portmap 8 , +.Xr rpcbind 8 , .Xr rpc.rwalld 8 .Sh HISTORY The diff --git a/usr.bin/rwall/rwall.c b/usr.bin/rwall/rwall.c index 16b985cd73..270053161f 100644 --- a/usr.bin/rwall/rwall.c +++ b/usr.bin/rwall/rwall.c @@ -33,7 +33,7 @@ * * @(#) Copyright (c) 1988 Regents of the University of California. All rights reserved. * @(#)wall.c 5.14 (Berkeley) 3/2/91 - * $FreeBSD: src/usr.bin/rwall/rwall.c,v 1.8.2.1 2001/02/18 02:27:54 kris Exp $ + * $FreeBSD: src/usr.bin/rwall/rwall.c,v 1.14 2005/05/21 09:55:08 ru Exp $ * $DragonFly: src/usr.bin/rwall/rwall.c,v 1.7 2005/07/30 16:44:12 liamfoy Exp $ */ @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -58,7 +57,6 @@ #include #include -static size_t mbufsize; static char *mbuf; static void makemsg(const char *); @@ -107,8 +105,8 @@ main(int argc, char **argv) tv.tv_sec = 15; /* XXX ?? */ tv.tv_usec = 0; - if (clnt_call(cl, WALLPROC_WALL, (xdrproc_t)xdr_wrapstring, &mbuf, xdr_void, - &res, tv) != RPC_SUCCESS) { + if (clnt_call(cl, WALLPROC_WALL, (xdrproc_t)xdr_wrapstring, &mbuf, + (xdrproc_t)xdr_void, &res, tv) != RPC_SUCCESS) { /* * An error occurred while calling the server. * Print error message and die. @@ -117,13 +115,13 @@ main(int argc, char **argv) exit(1); } - exit(0); + return(0); } static void usage(void) { - fprintf(stderr, "usage: rwall hostname [file]\n"); + fprintf(stderr, "usage: rwall host [file]\n"); exit(1); } @@ -136,6 +134,7 @@ makemsg(const char *fname) time_t now; FILE *fp; int fd; + size_t mbufsize; char hostname[MAXHOSTNAMELEN], lbuf[256], tmpname[MAXPATHLEN]; const char *whom, *tty; @@ -163,7 +162,7 @@ makemsg(const char *fname) fprintf(fp, "Remote Broadcast Message from %s@%s\n", whom, hostname); tty = ttyname(STDERR_FILENO); if (tty == NULL) - tty = "no tty"; + tty = "notty"; fprintf(fp, " (%s) at %d:%02d ...\n", tty, lt->tm_hour, lt->tm_min); @@ -180,7 +179,7 @@ makemsg(const char *fname) mbufsize = (size_t)sbuf.st_size; if ((mbuf = malloc(mbufsize)) == NULL) err(1, "malloc failed"); - if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) + if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != (u_int)mbufsize) err(1, "can't read temporary file"); if (close(fd)) warn("close failed"); diff --git a/usr.bin/showmount/showmount.8 b/usr.bin/showmount/showmount.8 index 7894155a7e..c5450e84c4 100644 --- a/usr.bin/showmount/showmount.8 +++ b/usr.bin/showmount/showmount.8 @@ -33,7 +33,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)showmount.8 8.3 (Berkeley) 3/29/95 -.\" $FreeBSD: src/usr.bin/showmount/showmount.8,v 1.8.2.3 2001/08/16 13:17:03 ru Exp $ +.\" $FreeBSD: src/usr.bin/showmount/showmount.8,v 1.18 2005/01/18 13:43:52 ru Exp $ .\" $DragonFly: src/usr.bin/showmount/showmount.8,v 1.3 2006/02/17 19:39:10 swildner Exp $ .\" .Dd March 29, 1995 @@ -44,11 +44,13 @@ .Nd show remote nfs mounts on host .Sh SYNOPSIS .Nm -.Op Fl ade3 +.Op Fl a | d +.Op Fl e3 .Op Ar host .Sh DESCRIPTION -.Nm Showmount -shows status information about the +The +.Nm +utility shows status information about the .Tn NFS server on .Ar host . @@ -64,7 +66,9 @@ and .%T "NFS: Network File System Version 3 Protocol Specification" , Appendix I, for a detailed description of the protocol. -.Bl -tag -width Ds +.Pp +The following options are available: +.Bl -tag -width indent .It Fl a List all mount points in the form: .Bd -ragged -offset indent -compact @@ -77,7 +81,9 @@ Show the .Ar host Ns 's exports list. .It Fl 3 -Use mount protocol Version 3, compatible with NFS Version 3. +Use mount protocol Version 3, compatible with +.Tn NFS +Version 3. .El .Sh SEE ALSO .Xr mount 8 , @@ -93,6 +99,7 @@ The mount daemon running on the server only has an idea of the actual mounts, since the .Tn NFS server is stateless. -.Nm Showmount -will only display the information +The +.Nm +utility will only display the information as accurately as the mount daemon reports it. diff --git a/usr.bin/showmount/showmount.c b/usr.bin/showmount/showmount.c index bb5e61a788..0fa10c8782 100644 --- a/usr.bin/showmount/showmount.c +++ b/usr.bin/showmount/showmount.c @@ -35,7 +35,7 @@ * * @(#) Copyright (c) 1989, 1993, 1995 The Regents of the University of California. All rights reserved. * @(#)showmount.c 8.3 (Berkeley) 3/29/95 - * $FreeBSD: src/usr.bin/showmount/showmount.c,v 1.8 1999/08/28 01:05:43 peter Exp $ + * $FreeBSD: src/usr.bin/showmount/showmount.c,v 1.16 2005/05/21 09:55:08 ru Exp $ * $DragonFly: src/usr.bin/showmount/showmount.c,v 1.5 2005/09/05 04:22:07 swildner Exp $ */ @@ -90,10 +90,8 @@ void print_dump(struct mountlist *); static void usage(void); int xdr_mntdump(XDR *, struct mountlist **); int xdr_exports(XDR *, struct exportslist **); -int tcp_callrpc(const char *host, - int prognum, int versnum, int procnum, - xdrproc_t inproc, char *in, - xdrproc_t outproc, char *out); +int tcp_callrpc(const char *, int, int, int, xdrproc_t, char *, xdrproc_t, + char *); /* * This command queries the NFS mount daemon for it's mount list and/or @@ -108,12 +106,11 @@ main(int argc, char **argv) struct exportslist *exp; struct grouplist *grp; int rpcs = 0, mntvers = 1; - char ch; const char *host; - int estat; + int ch, estat; while ((ch = getopt(argc, argv, "ade3")) != -1) - switch((char)ch) { + switch (ch) { case 'a': if (type == 0) { type = ALL; @@ -151,15 +148,15 @@ main(int argc, char **argv) if (rpcs & DODUMP) if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers, - RPCMNT_DUMP, xdr_void, (char *)0, - xdr_mntdump, (char *)&mntdump)) != 0) { + RPCMNT_DUMP, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) { clnt_perrno(estat); errx(1, "can't do mountdump rpc"); } if (rpcs & DOEXPORTS) if ((estat = tcp_callrpc(host, RPCPROG_MNT, mntvers, - RPCMNT_EXPORT, xdr_void, (char *)0, - xdr_exports, (char *)&exports)) != 0) { + RPCMNT_EXPORT, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_exports, (char *)&exports)) != 0) { clnt_perrno(estat); errx(1, "can't do exports rpc"); } @@ -204,58 +201,26 @@ main(int argc, char **argv) * tcp_callrpc has the same interface as callrpc, but tries to * use tcp as transport method in order to handle large replies. */ - -int +int tcp_callrpc(const char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out) { - struct hostent *hp; - struct sockaddr_in server_addr; CLIENT *client; - int sock; struct timeval timeout; int rval; - - hp = gethostbyname(host); - - if (!hp) - return ((int) RPC_UNKNOWNHOST); - 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; - - sock = RPC_ANYSOCK; - - client = clnttcp_create(&server_addr, - (u_long) prognum, - (u_long) versnum, &sock, 0, 0); - if (!client) { - timeout.tv_sec = 5; - timeout.tv_usec = 0; - server_addr.sin_port = 0; - sock = RPC_ANYSOCK; - client = clntudp_create(&server_addr, - (u_long) prognum, - (u_long) versnum, - timeout, - &sock); - } - if (!client) + if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL && + (client = clnt_create(host, prognum, versnum, "udp")) == NULL) return ((int) rpc_createerr.cf_stat); timeout.tv_sec = 25; timeout.tv_usec = 0; - rval = (int) clnt_call(client, procnum, + rval = (int) clnt_call(client, procnum, inproc, in, outproc, out, timeout); clnt_destroy(client); - return rval; + return rval; } /* @@ -271,14 +236,14 @@ xdr_mntdump(XDR *xdrsp, struct mountlist **mlp) int bool; char *strp; - *mlp = (struct mountlist *)0; + *mlp = NULL; if (!xdr_bool(xdrsp, &bool)) return (0); while (bool) { mp = (struct mountlist *)malloc(sizeof(struct mountlist)); if (mp == NULL) return (0); - mp->ml_left = mp->ml_right = (struct mountlist *)0; + mp->ml_left = mp->ml_right = NULL; strp = mp->ml_host; if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) return (0); @@ -349,14 +314,14 @@ xdr_exports(XDR *xdrsp, struct exportslist **exp) int bool, grpbool; char *strp; - *exp = (struct exportslist *)0; + *exp = NULL; if (!xdr_bool(xdrsp, &bool)) return (0); while (bool) { ep = (struct exportslist *)malloc(sizeof(struct exportslist)); if (ep == NULL) return (0); - ep->ex_groups = (struct grouplist *)0; + ep->ex_groups = NULL; strp = ep->ex_dirp; if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) return (0); @@ -385,7 +350,7 @@ xdr_exports(XDR *xdrsp, struct exportslist **exp) static void usage(void) { - fprintf(stderr, "usage: showmount [-ade3] host\n"); + fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n"); exit(1); } @@ -395,6 +360,7 @@ usage(void) void print_dump(struct mountlist *mp) { + if (mp == NULL) return; if (mp->ml_left) diff --git a/usr.bin/ypwhich/ypwhich.1 b/usr.bin/ypwhich/ypwhich.1 index 30cd86c8a9..9b152fb770 100644 --- a/usr.bin/ypwhich/ypwhich.1 +++ b/usr.bin/ypwhich/ypwhich.1 @@ -28,7 +28,7 @@ .\" (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: src/usr.bin/ypwhich/ypwhich.1,v 1.4.2.4 2002/06/21 15:30:38 charnier Exp $ +.\" $FreeBSD: src/usr.bin/ypwhich/ypwhich.1,v 1.10 2006/12/28 10:58:06 ru Exp $ .\" $DragonFly: src/usr.bin/ypwhich/ypwhich.1,v 1.2 2003/06/17 04:29:34 dillon Exp $ .\" .Dd February 23, 1994 @@ -74,13 +74,17 @@ to their corresponding map names. .It Fl m Op Ar mname Find the master .Tn YP -server for the named map. No +server for the named map. +No .Ar host may be specified with the .Fl m option. -.Ar Mname -can be a map name or nickname. If +The +.Ar mname +argument +can be a map name or nickname. +If .Ar mname is omitted, .Nm diff --git a/usr.bin/ypwhich/ypwhich.c b/usr.bin/ypwhich/ypwhich.c index 8cda2eb599..d28927e9a2 100644 --- a/usr.bin/ypwhich/ypwhich.c +++ b/usr.bin/ypwhich/ypwhich.c @@ -26,15 +26,23 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.bin/ypwhich/ypwhich.c,v 1.11.2.1 2002/02/15 00:46:56 des Exp $ + * $FreeBSD: src/usr.bin/ypwhich/ypwhich.c,v 1.16 2004/04/04 19:17:38 charnier Exp $ * $DragonFly: src/usr.bin/ypwhich/ypwhich.c,v 1.3 2003/10/04 20:36:55 hmp Exp $ */ #include #include #include + +#include +#include +#include +#include + #include + #include + #include #include #include @@ -42,11 +50,6 @@ #include #include #include -#include -#include -#include -struct dom_binding{}; -#include #define ERR_USAGE 1 /* bad arguments - display 'usage' message */ #define ERR_NOSUCHHOST 2 /* no such host */ @@ -83,8 +86,8 @@ usage(void) /* * Like yp_bind except can query a specific host */ -int -bind_host(char *dom, struct sockaddr_in *sin) +static int +bind_host(char *dom, struct sockaddr_in *lsin) { struct hostent *hent = NULL; struct ypbind_resp ypbr; @@ -96,7 +99,7 @@ bind_host(char *dom, struct sockaddr_in *sin) sock = RPC_ANYSOCK; tv.tv_sec = 15; tv.tv_usec = 0; - client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock); + client = clntudp_create(lsin, YPBINDPROG, YPBINDVERS, tv, &sock); if (client == NULL) { warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND)); return (YPERR_YPBIND); @@ -105,7 +108,8 @@ bind_host(char *dom, struct sockaddr_in *sin) tv.tv_sec = 5; tv.tv_usec = 0; r = clnt_call(client, YPBINDPROC_DOMAIN, - xdr_domainname, &dom, xdr_ypbind_resp, &ypbr, tv); + (xdrproc_t)xdr_domainname, &dom, + (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); if (r != RPC_SUCCESS) { warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND)); clnt_destroy(client); @@ -113,14 +117,14 @@ bind_host(char *dom, struct sockaddr_in *sin) } else { if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { warnx("can't yp_bind: reason: %s", - ypbinderr_string(ypbr.ypbind_resp_u.ypbind_error)); + ypbinderr_string(ypbr.ypbind_respbody.ypbind_error)); clnt_destroy(client); return (r); } } clnt_destroy(client); - ss_addr = *(struct in_addr *)ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr; + ss_addr = ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr; /*printf("%08x\n", ss_addr);*/ hent = gethostbyaddr(&ss_addr, sizeof(ss_addr), AF_INET); if (hent) @@ -133,12 +137,14 @@ bind_host(char *dom, struct sockaddr_in *sin) int main(int argc, char **argv) { - char *domainname = NULL, *master, *map = NULL; + char *domnam = NULL, *master; + char *map = NULL; struct ypmaplist *ypml, *y; struct hostent *hent; - struct sockaddr_in sin; + struct sockaddr_in lsin; int notrans, mode, getmap; - int c, r, i; + int c, r; + u_int i; getmap = notrans = mode = 0; while ((c = getopt(argc, argv, "xd:mt")) != -1) @@ -150,7 +156,7 @@ main(int argc, char **argv) ypaliases[i].name); exit(0); case 'd': - domainname = optarg; + domnam = optarg; break; case 't': notrans++; @@ -162,30 +168,30 @@ main(int argc, char **argv) usage(); } - if (!domainname) - yp_get_default_domain(&domainname); + if (!domnam) + yp_get_default_domain(&domnam); if (mode == 0) { switch (argc-optind) { case 0: - bzero(&sin, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + bzero(&lsin, sizeof lsin); + lsin.sin_family = AF_INET; + lsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (bind_host(domainname, &sin)) + if (bind_host(domnam, &lsin)) exit(ERR_NOBINDING); break; case 1: - bzero(&sin, sizeof sin); - sin.sin_family = AF_INET; - if ((sin.sin_addr.s_addr = inet_addr(argv[optind])) == -1) { + bzero(&lsin, sizeof lsin); + lsin.sin_family = AF_INET; + if ((lsin.sin_addr.s_addr = inet_addr(argv[optind])) == INADDR_NONE) { hent = gethostbyname(argv[optind]); if (!hent) errx(ERR_NOSUCHHOST, "host %s unknown", argv[optind]); bcopy((char *)hent->h_addr_list[0], - (char *)&sin.sin_addr, sizeof sin.sin_addr); + (char *)&lsin.sin_addr, sizeof lsin.sin_addr); } - if (bind_host(domainname, &sin)) + if (bind_host(domnam, &lsin)) exit(ERR_NOBINDING); break; default: @@ -202,7 +208,7 @@ main(int argc, char **argv) for (i = 0; (!notrans) && imap, &master); + r = yp_master(domnam, ypml->ypml_name, &master); switch (r) { case 0: - printf("%s %s\n", ypml->map, master); + printf("%s %s\n", ypml->ypml_name, master); free(master); break; default: warnx("can't find the master of %s: reason: %s", - ypml->map, yperr_string(r)); + ypml->ypml_name, yperr_string(r)); break; } - y = ypml->next; + y = ypml->ypml_next; free(ypml); } break; case YPERR_YPBIND: errx(ERR_NOYPBIND, "not running ypbind"); default: - errx(ERR_NOMASTER, "can't get map list for domain %s. reason: %s", - domainname, yperr_string(r)); + errx(ERR_NOMASTER, "can't get map list for domain %s: reason: %s", + domnam, yperr_string(r)); } exit(0); } diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index e54205c1ba..76082d89f2 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -76,7 +76,6 @@ SUBDIR= 802_11 \ pfctl \ pflogd \ pnpinfo \ - portmap \ ppp \ pppctl \ pppd \ @@ -101,6 +100,7 @@ SUBDIR= 802_11 \ rpc.yppasswdd \ rpc.ypupdated \ rpc.ypxfrd \ + rpcbind \ rrenumd \ rtadvd \ rtprio \ diff --git a/usr.sbin/bootparamd/bootparamd/Makefile b/usr.sbin/bootparamd/bootparamd/Makefile index c082165d6a..14e7c655a6 100644 --- a/usr.sbin/bootparamd/bootparamd/Makefile +++ b/usr.sbin/bootparamd/bootparamd/Makefile @@ -1,23 +1,28 @@ # from: @(#)Makefile 5.8 (Berkeley) 7/28/90 -# $FreeBSD: src/usr.sbin/bootparamd/bootparamd/Makefile,v 1.11.2.1 2001/04/25 12:09:20 ru Exp $ +# $FreeBSD: src/usr.sbin/bootparamd/bootparamd/Makefile,v 1.15 2004/11/13 20:40:31 bz Exp $ # $DragonFly: src/usr.sbin/bootparamd/bootparamd/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $ PROG= bootparamd +MAN= bootparams.5 bootparamd.8 SRCS= bootparamd.c main.c ${GENSRCS} GENSRCS=bootparam_prot.h bootparam_prot_svc.c bootparam_prot_xdr.c -MAN= bootparams.5 bootparamd.8 + CFLAGS+= -DTFTP_DIR=\"/tftpboot\" -I. +.if !defined(NO_NIS) +CFLAGS+= -DYP +.endif + CLEANFILES= ${GENSRCS} RPCSRC= ${DESTDIR}/usr/include/rpcsvc/bootparam_prot.x bootparam_prot_svc.c: ${RPCSRC} - rpcgen -m -o ${.TARGET} ${RPCSRC} + rpcgen -C -m -o ${.TARGET} ${RPCSRC} bootparam_prot_xdr.c: ${RPCSRC} - rpcgen -c -o ${.TARGET} ${RPCSRC} + rpcgen -C -c -o ${.TARGET} ${RPCSRC} bootparam_prot.h: ${RPCSRC} - rpcgen -h -o ${.TARGET} ${RPCSRC} + rpcgen -C -h -o ${.TARGET} ${RPCSRC} .include diff --git a/usr.sbin/bootparamd/bootparamd/README b/usr.sbin/bootparamd/bootparamd/README index 85a2a5444f..53cae86618 100644 --- a/usr.sbin/bootparamd/bootparamd/README +++ b/usr.sbin/bootparamd/bootparamd/README @@ -1,4 +1,5 @@ - +$FreeBSD: src/usr.sbin/bootparamd/bootparamd/README,v 1.2 2001/07/23 12:05:27 kris Exp $ +$DragonFly$ This directory contains a version of the rpc.bootparamd, which have been written using the Sun's RPC protocol for bootparamd. To use it you must @@ -40,7 +41,7 @@ CALLBOOTD The debugging tool callbootd is used to check the response you get to a specific (booting) request. It can be used as - callbootd server inet-adress + callbootd server inet-address or callbootd server hostname file where "server" is a machine running the rpc.bootparamd program, "inet-address" diff --git a/usr.sbin/bootparamd/bootparamd/bootparamd.8 b/usr.sbin/bootparamd/bootparamd/bootparamd.8 index 62ab78a81a..6bd817a08a 100644 --- a/usr.sbin/bootparamd/bootparamd/bootparamd.8 +++ b/usr.sbin/bootparamd/bootparamd/bootparamd.8 @@ -1,5 +1,5 @@ .\" @(#)bootparamd.8 -.\" $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.8,v 1.9.2.5 2003/03/11 21:13:48 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.8,v 1.15 2005/01/18 20:02:31 ru Exp $ .\" $DragonFly: src/usr.sbin/bootparamd/bootparamd/bootparamd.8,v 1.3 2006/02/17 19:40:12 swildner Exp $ .Dd December 14, 2000 .Dt BOOTPARAMD 8 diff --git a/usr.sbin/bootparamd/bootparamd/bootparamd.c b/usr.sbin/bootparamd/bootparamd/bootparamd.c index ca1bb25d26..9c8b59d8f9 100644 --- a/usr.sbin/bootparamd/bootparamd/bootparamd.c +++ b/usr.sbin/bootparamd/bootparamd/bootparamd.c @@ -8,12 +8,15 @@ use and modify. Please send modifications and/or suggestions + bug fixes to */ /* - * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.10 1999/08/28 01:15:39 peter Exp $ + * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.14 2008/01/30 13:48:37 rink Exp $ * $DragonFly: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.4 2003/11/15 23:33:35 eirikn Exp $ */ + +#ifdef YP #include #include #include +#endif #include "bootparam_prot.h" #include #include @@ -25,7 +28,7 @@ use and modify. Please send modifications and/or suggestions + bug fixes to #include #include extern int debug, dolog; -extern unsigned long route_addr; +extern in_addr_t route_addr; extern char *bootpfile; #define MAXLEN 800 @@ -41,9 +44,9 @@ int getthefile(char *, char *, char *, int); int checkhost(char *, char *, int); bp_whoami_res * -bootparamproc_whoami_1(bp_whoami_arg *whoami) +bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *req) { - long haddr; + in_addr_t haddr; static bp_whoami_res res; if (debug) fprintf(stderr,"whoami got question for %d.%d.%d.%d\n", @@ -76,7 +79,7 @@ bootparamproc_whoami_1(bp_whoami_arg *whoami) if ( res.router_address.address_type != IP_ADDR_TYPE ) { res.router_address.address_type = IP_ADDR_TYPE; - bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, 4); + bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t)); } if (debug) fprintf(stderr, "Returning %s %s %d.%d.%d.%d\n", @@ -105,7 +108,7 @@ bootparamproc_whoami_1(bp_whoami_arg *whoami) bp_getfile_res * -bootparamproc_getfile_1(bp_getfile_arg *getfile) +bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *req) { char *where, *index(); static bp_getfile_res res; @@ -183,7 +186,9 @@ getthefile(char *askname, char *fileid, char *buffer, int blen) char *where; static char *result; int resultlen; +#ifdef YP static char *yp_domain; +#endif int ch, pch, fid_len, res = 0; int match = 0; @@ -204,6 +209,7 @@ getthefile(char *askname, char *fileid, char *buffer, int blen) } } if (*hostname == '+' ) { /* NIS */ +#ifdef YP if (yp_get_default_domain(&yp_domain)) { if (debug) warn("NIS"); return(0); @@ -222,6 +228,9 @@ getthefile(char *askname, char *fileid, char *buffer, int blen) if (fclose(bpf)) warnx("could not close %s", bootpfile); return(1); +#else + return(0); /* ENOTSUP */ +#endif } /* skip to next entry */ if ( match ) break; @@ -277,7 +286,9 @@ checkhost(char *askname, char *hostname, int len) int res = 0; static char *result; int resultlen; +#ifdef YP static char *yp_domain; +#endif /* struct hostent *cmp_he;*/ @@ -304,6 +315,7 @@ checkhost(char *askname, char *hostname, int len) } } if (*hostname == '+' ) { /* NIS */ +#ifdef YP if (yp_get_default_domain(&yp_domain)) { if (debug) warn("NIS"); return(0); @@ -321,6 +333,9 @@ checkhost(char *askname, char *hostname, int len) if (fclose(bpf)) warnx("could not close %s", bootpfile); return(res); +#else + return(0); /* ENOTSUP */ +#endif } /* skip to next entry */ pch = ch = getc(bpf); diff --git a/usr.sbin/bootparamd/bootparamd/main.c b/usr.sbin/bootparamd/bootparamd/main.c index 9bce2d7ad6..5e4190f59a 100644 --- a/usr.sbin/bootparamd/bootparamd/main.c +++ b/usr.sbin/bootparamd/bootparamd/main.c @@ -8,7 +8,7 @@ use and modify. Please send modifications and/or suggestions + bug fixes to */ /* - * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/main.c,v 1.9 1999/08/28 01:15:39 peter Exp $ + * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/main.c,v 1.14 2008/08/02 00:10:02 cognet Exp $ * $DragonFly: src/usr.sbin/bootparamd/bootparamd/main.c,v 1.6 2008/09/19 18:48:33 swildner Exp $ */ #include @@ -31,7 +31,7 @@ use and modify. Please send modifications and/or suggestions + bug fixes to int debug = 0; int dolog = 0; -unsigned long route_addr = -1; +in_addr_t route_addr = -1; struct sockaddr_in my_addr; char *bootpfile = "/etc/bootparams"; @@ -44,7 +44,7 @@ main(int argc, char **argv) SVCXPRT *transp; struct hostent *he; struct stat buf; - char c; + int c; while ((c = getopt(argc, argv,"dsr:f:")) != -1) switch (c) { @@ -52,7 +52,7 @@ main(int argc, char **argv) debug = 1; break; case 'r': - if ( isdigit( *optarg)) { + if (isdigit((unsigned char)*optarg)) { route_addr = inet_addr(optarg); break; } else { diff --git a/usr.sbin/keyserv/Makefile b/usr.sbin/keyserv/Makefile index e64575c530..65affe4516 100644 --- a/usr.sbin/keyserv/Makefile +++ b/usr.sbin/keyserv/Makefile @@ -2,7 +2,7 @@ # $DragonFly: src/usr.sbin/keyserv/Makefile,v 1.5 2008/11/03 00:25:45 pavalos Exp $ PROG= keyserv -SRCS= keyserv.c setkey.c keyserv_uid.c crypt_svc.c crypt_server.c crypt.h +SRCS= keyserv.c setkey.c crypt_svc.c crypt_server.c crypt.h WARNS?= 1 MAN= keyserv.8 diff --git a/usr.sbin/keyserv/keyserv.c b/usr.sbin/keyserv/keyserv.c index 1574c1fae1..24ce5fed4c 100644 --- a/usr.sbin/keyserv/keyserv.c +++ b/usr.sbin/keyserv/keyserv.c @@ -5,29 +5,29 @@ * 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 * * @(#)keyserv.c 1.15 94/04/25 SMI - * $FreeBSD: src/usr.sbin/keyserv/keyserv.c,v 1.3.2.2 2001/07/19 10:58:22 roam Exp $ + * $FreeBSD: src/usr.sbin/keyserv/keyserv.c,v 1.12 2007/11/07 10:53:35 kevlo Exp $ * $DragonFly: src/usr.sbin/keyserv/keyserv.c,v 1.6 2004/12/18 22:48:03 swildner Exp $ */ @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -108,10 +107,11 @@ main(int argc, char **argv) { int nflag = 0; int c; - SVCXPRT *transp; - int sock = RPC_ANYSOCK; int warn = 0; char *path = NULL; + void *localhandle; + SVCXPRT *transp; + struct netconfig *nconf = NULL; __key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog; __key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog; @@ -150,46 +150,53 @@ main(int argc, char **argv) /* * Initialize */ - umask(066); /* paranoia */ + umask(S_IXUSR|S_IXGRP|S_IXOTH); if (geteuid() != 0) errx(1, "keyserv must be run as root"); setmodulus(HEXMODULUS); getrootkey(&masterkey, nflag); + rpcb_unset(KEY_PROG, KEY_VERS, NULL); + rpcb_unset(KEY_PROG, KEY_VERS2, NULL); - /* Create services. */ + if (svc_create(keyprogram, KEY_PROG, KEY_VERS, + "netpath") == 0) { + fprintf(stderr, "%s: unable to create service\n", argv[0]); + exit(1); + } - pmap_unset(KEY_PROG, KEY_VERS); - pmap_unset(KEY_PROG, KEY_VERS2); - unlink(KEYSERVSOCK); + if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, + "netpath") == 0) { + fprintf(stderr, "%s: unable to create service\n", argv[0]); + exit(1); + } - 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)"); + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } - 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 (nconf == NULL) + errx(1, "getnetconfig: %s", nc_sperror()); + + unlink(KEYSERVSOCK); + rpcb_unset(CRYPT_PROG, CRYPT_VERS, nconf); + transp = svcunix_create(RPC_ANYSOCK, 0, 0, KEYSERVSOCK); if (transp == NULL) - errx(1, "cannot create AF_UNIX service"); - if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, 0)) + errx(1, "cannot create AF_LOCAL service"); + if (!svc_reg(transp, KEY_PROG, KEY_VERS, keyprogram, nconf)) errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)"); - if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, 0)) + if (!svc_reg(transp, KEY_PROG, KEY_VERS2, keyprogram, nconf)) errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)"); - if (!svc_register(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, 0)) + if (!svc_reg(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, nconf)) errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)"); + endnetconfig(localhandle); + + umask(066); /* paranoia */ + if (!debugging) { daemon(0,0); } @@ -208,28 +215,14 @@ main(int argc, char **argv) static void randomize(des_block *master) { - int i; - int seed; - struct timeval tv; - int shift; - - seed = 0; - for (i = 0; i < 1024; i++) { - gettimeofday(&tv, (struct timezone *) NULL); - shift = i % 8 * sizeof (int); - seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift)); - } #ifdef KEYSERV_RANDOM - srandom(seed); - master->key.low = random(); - master->key.high = random(); - srandom(seed); + master->key.low = arc4random(); + master->key.high = arc4random(); #else /* use stupid dangerous bad rand() */ - srand(seed); + sranddev(); master->key.low = rand(); master->key.high = rand(); - srand(seed); #endif } @@ -592,83 +585,83 @@ keyprogram(struct svc_req *rqstp, SVCXPRT *transp) netobj key_get_conv_2_arg; } argument; char *result; - bool_t(*xdr_argument)(), (*xdr_result)(); + xdrproc_t xdr_argument, xdr_result; char *(*local) (); uid_t uid = -1; int check_auth; switch (rqstp->rq_proc) { case NULLPROC: - svc_sendreply(transp, xdr_void, (char *)NULL); + svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); return; case KEY_SET: - xdr_argument = xdr_keybuf; - xdr_result = xdr_int; + xdr_argument = (xdrproc_t)xdr_keybuf; + xdr_result = (xdrproc_t)xdr_int; local = (char *(*)()) key_set_1_svc_prog; check_auth = 1; break; case KEY_ENCRYPT: - xdr_argument = xdr_cryptkeyarg; - xdr_result = xdr_cryptkeyres; + xdr_argument = (xdrproc_t)xdr_cryptkeyarg; + xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_encrypt_1_svc_prog; check_auth = 1; break; case KEY_DECRYPT: - xdr_argument = xdr_cryptkeyarg; - xdr_result = xdr_cryptkeyres; + xdr_argument = (xdrproc_t)xdr_cryptkeyarg; + xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_decrypt_1_svc_prog; check_auth = 1; break; case KEY_GEN: - xdr_argument = xdr_void; - xdr_result = xdr_des_block; + xdr_argument = (xdrproc_t)xdr_void; + xdr_result = (xdrproc_t)xdr_des_block; local = (char *(*)()) key_gen_1_svc_prog; check_auth = 0; break; case KEY_GETCRED: - xdr_argument = xdr_netnamestr; - xdr_result = xdr_getcredres; + xdr_argument = (xdrproc_t)xdr_netnamestr; + xdr_result = (xdrproc_t)xdr_getcredres; local = (char *(*)()) key_getcred_1_svc_prog; check_auth = 0; break; case KEY_ENCRYPT_PK: - xdr_argument = xdr_cryptkeyarg2; - xdr_result = xdr_cryptkeyres; + xdr_argument = (xdrproc_t)xdr_cryptkeyarg2; + xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_encrypt_pk_2_svc_prog; check_auth = 1; break; case KEY_DECRYPT_PK: - xdr_argument = xdr_cryptkeyarg2; - xdr_result = xdr_cryptkeyres; + xdr_argument = (xdrproc_t)xdr_cryptkeyarg2; + xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_decrypt_pk_2_svc_prog; check_auth = 1; break; case KEY_NET_PUT: - xdr_argument = xdr_key_netstarg; - xdr_result = xdr_keystatus; + xdr_argument = (xdrproc_t)xdr_key_netstarg; + xdr_result = (xdrproc_t)xdr_keystatus; local = (char *(*)()) key_net_put_2_svc_prog; check_auth = 1; break; case KEY_NET_GET: xdr_argument = (xdrproc_t) xdr_void; - xdr_result = xdr_key_netstres; + xdr_result = (xdrproc_t)xdr_key_netstres; local = (char *(*)()) key_net_get_2_svc_prog; check_auth = 1; break; case KEY_GET_CONV: xdr_argument = (xdrproc_t) xdr_keybuf; - xdr_result = xdr_cryptkeyres; + xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_get_conv_2_svc_prog; check_auth = 1; break; @@ -696,18 +689,18 @@ keyprogram(struct svc_req *rqstp, SVCXPRT *transp) uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid; } - memset((char *) &argument, 0, sizeof (argument)); - if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { + memset(&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { svcerr_decode(transp); return; } result = (*local) (uid, &argument); - if (!svc_sendreply(transp, xdr_result, (char *) result)) { + if (!svc_sendreply(transp, xdr_result, result)) { if (debugging) fprintf(stderr, "unable to reply\n"); svcerr_systemerr(transp); } - if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { + if (!svc_freeargs(transp, xdr_argument, &argument)) { if (debugging) fprintf(stderr, "unable to free arguments\n"); exit(1); @@ -719,16 +712,16 @@ static int root_auth(SVCXPRT *trans, struct svc_req *rqstp) { uid_t uid; - struct sockaddr_in *remote; + struct sockaddr *remote; - remote = svc_getcaller(trans); - if (remote->sin_family == AF_INET) { + remote = svc_getrpccaller(trans)->buf; + if (remote->sa_family != AF_UNIX) { if (debugging) fprintf(stderr, "client didn't use AF_UNIX\n"); return (0); } - if (__rpc_get_local_uid(&uid, trans) < 0) { + if (__rpc_get_local_uid(trans, &uid) < 0) { if (debugging) fprintf(stderr, "__rpc_get_local_uid failed\n"); return (0); diff --git a/usr.sbin/keyserv/keyserv.h b/usr.sbin/keyserv/keyserv.h index 8d69a656dd..743f99695c 100644 --- a/usr.sbin/keyserv/keyserv.h +++ b/usr.sbin/keyserv/keyserv.h @@ -1,4 +1,5 @@ /* + * $FreeBSD: src/usr.sbin/keyserv/keyserv.h,v 1.5 2007/11/07 10:53:35 kevlo Exp $ * $DragonFly: src/usr.sbin/keyserv/keyserv.h,v 1.6 2006/08/03 16:40:48 swildner Exp $ */ @@ -12,9 +13,7 @@ extern keystatus pk_netget( uid_t, key_netstarg * ); extern keystatus pk_get_conv_key( uid_t, keybuf, cryptkeyres * ); extern void pk_nodefaultkeys( void ); -extern int __rpc_get_local_uid( uid_t * , SVCXPRT * ); extern void crypt_prog_1( struct svc_req *, SVCXPRT * ); extern void load_des( int, char * ); extern int (*_my_crypt)( char *, int, struct desparams * ); - diff --git a/usr.sbin/keyserv/keyserv_uid.c b/usr.sbin/keyserv/keyserv_uid.c deleted file mode 100644 index ce4aad1b92..0000000000 --- a/usr.sbin/keyserv/keyserv_uid.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 1996 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/usr.sbin/keyserv/keyserv_uid.c,v 1.3 1999/08/28 01:16:41 peter Exp $ - * $DragonFly: src/usr.sbin/keyserv/keyserv_uid.c,v 1.3 2003/11/16 15:17:36 eirikn Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "keyserv.h" - -/* - * XXX should be declared somewhere - */ -struct cmessage { - struct cmsghdr cmsg; - struct cmsgcred cmcred; -}; - -int -__rpc_get_local_uid(uid_t *uid, SVCXPRT *transp) -{ - struct cmessage *cm; - - if (transp->xp_verf.oa_length < sizeof(struct cmessage) || - transp->xp_verf.oa_base == NULL || - transp->xp_verf.oa_flavor != AUTH_UNIX) - return(-1); - - cm = (struct cmessage *)transp->xp_verf.oa_base; - if (cm->cmsg.cmsg_type != SCM_CREDS) - return(-1); - - *uid = cm->cmcred.cmcred_euid; - return(0); -} diff --git a/usr.sbin/portmap/Makefile b/usr.sbin/portmap/Makefile deleted file mode 100644 index b205fb1cce..0000000000 --- a/usr.sbin/portmap/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# @(#)Makefile 8.1 (Berkeley) 6/6/93 -# $FreeBSD: src/usr.sbin/portmap/Makefile,v 1.7.2.1 2001/04/25 12:10:33 ru Exp $ -# $DragonFly: src/usr.sbin/portmap/Makefile,v 1.2 2003/06/17 04:30:00 dillon Exp $ - -PROG= portmap -MAN= 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 diff --git a/usr.sbin/portmap/from_local.c b/usr.sbin/portmap/from_local.c deleted file mode 100644 index 01b59583ba..0000000000 --- a/usr.sbin/portmap/from_local.c +++ /dev/null @@ -1,225 +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 - * - * @(#) from_local.c 1.2 93/11/16 21:50:02 - * $FreeBSD: src/usr.sbin/portmap/from_local.c,v 1.10.2.1 2000/08/16 14:04:37 brian Exp $ - * $DragonFly: src/usr.sbin/portmap/from_local.c,v 1.3 2004/03/30 02:58:59 cpressey Exp $ - */ - -#ifdef TEST -#undef perror -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#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(void) -{ - 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(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(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 19323b9479..0000000000 --- a/usr.sbin/portmap/pmap_check.c +++ /dev/null @@ -1,251 +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. - */ - -/* - * @(#) pmap_check.c 1.6 93/11/21 20:58:59 - * $FreeBSD: src/usr.sbin/portmap/pmap_check.c,v 1.6 2000/01/15 23:08:28 brian Exp $ - * $DragonFly: src/usr.sbin/portmap/pmap_check.c,v 1.5 2007/11/25 01:28:24 swildner Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#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(int, struct sockaddr_in *, u_long, u_long, const char *); -static void toggle_verboselog(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(void) -{ - /* - * 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); - } - signal(SIGINT, toggle_verboselog); -} - -/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */ - -int -check_default(struct sockaddr_in *addr, u_long proc, u_long 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(struct sockaddr_in *addr, - u_long proc, u_long prog, u_long 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(struct sockaddr_in *addr, - u_long proc, u_long prog, u_long port) -{ - if (!from_local(addr)) { -#ifdef HOSTS_ACCESS - 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(struct sockaddr_in *addr, u_long proc, u_long prog, u_long 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(int sig) -{ - signal(sig, toggle_verboselog); - verboselog = !verboselog; -} - -/* logit - report events of interest via the syslog daemon */ - -static void -logit(int severity, struct sockaddr_in *addr, u_long procnum, u_long 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_check.h b/usr.sbin/portmap/pmap_check.h deleted file mode 100644 index ae912ee47b..0000000000 --- a/usr.sbin/portmap/pmap_check.h +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * Copyright (c) 2000 Brian Somers - * 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. - * - * @(#) pmap_check.h 1.3 93/11/21 16:18:53 - * - * $FreeBSD: src/usr.sbin/portmap/pmap_check.h,v 1.3 2000/01/15 23:08:28 brian Exp $ - * $DragonFly: src/usr.sbin/portmap/pmap_check.h,v 1.3 2003/11/03 19:31:40 eirikn Exp $ - */ - -extern int from_local(struct sockaddr_in *); -extern void check_startup(void); -extern int check_default(struct sockaddr_in *, u_long, u_long); -extern int check_setunset(struct sockaddr_in *, u_long, u_long, u_long); -extern int check_privileged_port(struct sockaddr_in *, u_long, u_long, - u_long); -extern int check_callit(struct sockaddr_in *, u_long, u_long, u_long); - -extern int verboselog; -extern int allow_severity; -extern int deny_severity; diff --git a/usr.sbin/portmap/pmap_dump/Makefile b/usr.sbin/portmap/pmap_dump/Makefile deleted file mode 100644 index 0064f28630..0000000000 --- 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 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 4f6475b8ce..0000000000 --- a/usr.sbin/portmap/pmap_dump/pmap_dump.c +++ /dev/null @@ -1,65 +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. - */ - -/* - * @(#) pmap_dump.c 1.1 92/06/11 22:53:15 - * $FreeBSD: src/usr.sbin/portmap/pmap_dump/pmap_dump.c,v 1.6 2000/01/15 23:08:30 brian Exp $ - * $DragonFly: src/usr.sbin/portmap/pmap_dump/pmap_dump.c,v 1.4 2004/03/30 02:59:00 cpressey Exp $ - */ - -#include -#ifdef SYSV40 -#include -#include -#else -#include -#endif -#include -#include -#include - -#include - -static const char *protoname(u_long); - -int -main(int argc, char **argv) -{ - struct sockaddr_in addr; - struct pmaplist *list; - 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(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 987e3209d3..0000000000 --- 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 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 dd505ea1c1..0000000000 --- a/usr.sbin/portmap/pmap_set/pmap_set.c +++ /dev/null @@ -1,72 +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. - */ - -/* - * @(#) pmap_set.c 1.1 92/06/11 22:53:16 - * $FreeBSD: src/usr.sbin/portmap/pmap_set/pmap_set.c,v 1.6 2000/01/15 23:08:30 brian Exp $ - * $DragonFly: src/usr.sbin/portmap/pmap_set/pmap_set.c,v 1.4 2004/03/30 02:59:00 cpressey Exp $ - */ - -#include -#ifdef SYSV40 -#include -#endif -#include -#include - -#include -#include - -static int parse_line(char *, u_long *, u_long *, int *, unsigned *); - -int -main(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(char *buf, u_long *prog, u_long *vers, int *prot, - unsigned int *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 f3ec60b6e9..0000000000 --- a/usr.sbin/portmap/portmap.8 +++ /dev/null @@ -1,145 +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: src/usr.sbin/portmap/portmap.8,v 1.7.2.4 2002/04/04 11:00:38 dd Exp $ -.\" $DragonFly: src/usr.sbin/portmap/portmap.8,v 1.3 2006/02/17 19:40:20 swildner Exp $ -.\" -.Dd June 6, 1993 -.Dt PORTMAP 8 -.Os -.Sh NAME -.Nm portmap -.Nd -.Tn RPC -program,version -to -.Tn DARPA -port mapper -.Sh SYNOPSIS -.Nm -.Op Fl d -.Op Fl v -.Op Fl h Ar bindip -.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. -.It Fl h -Specify specific IP addresses to bind to for UDP requests. -This option -may be specified multiple times and is typically necessary when running -on a multi-homed host. -If no -.Fl h -option is specified, -.Nm -will bind to -.Dv INADDR_ANY , -which could lead to problems on a multi-homed host due to -.Nm -returning a UDP packet from a different IP address than it was -sent to. -Note that when specifying IP addresses with -.Fl h , -.Nm -will automatically add -.Li 127.0.0.1 -to the list. -.El -.Sh SEE ALSO -.Xr hosts_access 5 , -.Xr inetd.conf 5 , -.Xr inetd 8 , -.Xr rpcinfo 8 -.Sh HISTORY -The -.Nm -command appeared in -.Bx 4.3 . -.Sh BUGS -If -.Nm -crashes, all servers must be restarted. diff --git a/usr.sbin/portmap/portmap.c b/usr.sbin/portmap/portmap.c deleted file mode 100644 index a63749aa1d..0000000000 --- a/usr.sbin/portmap/portmap.c +++ /dev/null @@ -1,620 +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. - * - * @(#) Copyright (c) 1990, 1993 The Regents of the University of California. All rights reserved. - * @(#)portmap.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.sbin/portmap/portmap.c,v 1.10.2.3 2002/05/06 18:18:21 dwmalone Exp $ - * $DragonFly: src/usr.sbin/portmap/portmap.c,v 1.4 2004/03/30 02:58:59 cpressey Exp $ - */ - -/* -@(#)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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pmap_check.h" - -static void reg_service(struct svc_req *, SVCXPRT *); -static void reap(int); -static void callit(struct svc_req *, SVCXPRT *); -static void usage(void); - -struct pmaplist *pmaplist; -int debugging = 0; - -int -main(int argc, char **argv) -{ - SVCXPRT *xprt; - int sock, c; - char **hosts = NULL; - int nhosts = 0; - struct sockaddr_in addr; - int len = sizeof(struct sockaddr_in); - struct pmaplist *pml; - - while ((c = getopt(argc, argv, "dvh:")) != -1) { - switch (c) { - - case 'd': - debugging = 1; - break; - - case 'v': - verboselog = 1; - break; - - case 'h': - ++nhosts; - hosts = realloc(hosts, nhosts * sizeof(char *)); - hosts[nhosts - 1] = optarg; - break; - - default: - usage(); - } - } - - if (!debugging && daemon(0, 0)) - err(1, "fork"); - - openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID, - LOG_DAEMON); - - bzero(&addr, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(PMAPPORT); - - /* - * If no hosts were specified, just bind to INADDR_ANY. Otherwise - * make sure 127.0.0.1 is added to the list. - */ - ++nhosts; - hosts = realloc(hosts, nhosts * sizeof(char *)); - if (nhosts == 1) - hosts[0] = "0.0.0.0"; - else - hosts[nhosts - 1] = "127.0.0.1"; - - /* - * Add UDP socket(s) - bind to specific IPs if asked to - */ - while (nhosts > 0) { - --nhosts; - - if (!inet_aton(hosts[nhosts], &addr.sin_addr)) { - syslog(LOG_ERR, "bad IP address: %s", hosts[nhosts]); - exit(1); - } - if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - syslog(LOG_ERR, "cannot create udp socket: %m"); - exit(1); - } - - 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; - - /* - * Add TCP socket - */ - addr.sin_addr.s_addr = 0; - 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; - - svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); - - /* additional initializations */ - check_startup(); - signal(SIGCHLD, reap); - svc_run(); - syslog(LOG_ERR, "svc_run returned unexpectedly"); - abort(); -} - -static void -usage(void) -{ - fprintf(stderr, "usage: portmap [-dv] [-h bindip]\n"); - exit(1); -} - -#ifndef lint -/* need to override perror calls in rpc library */ -void -perror(const char *what) -{ - syslog(LOG_ERR, "%s: %m", what); -} -#endif - -static struct pmaplist * -find_service(u_long prog, u_long vers, u_long prot) -{ - struct pmaplist *hit = NULL; - 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(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) - 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)®)) - 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) { - 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)®)) - 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) { - 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)®)) - 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) { - 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) { - 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(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(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(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(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(XDR *xdrs, struct rmtcallargs *cap) -{ - 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(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); - } - close(so); - exit(0); -} - -static void -reap(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 d40fa53f31..479cbe2399 100644 --- a/usr.sbin/rpc.lockd/Makefile +++ b/usr.sbin/rpc.lockd/Makefile @@ -1,40 +1,30 @@ -# $FreeBSD: src/usr.sbin/rpc.lockd/Makefile,v 1.8.2.2 2001/08/01 06:39:36 alfred Exp $ +# $NetBSD: Makefile,v 1.12 2000/08/07 16:23:31 thorpej Exp $ +# $FreeBSD: src/usr.sbin/rpc.lockd/Makefile,v 1.19 2003/10/26 06:10:44 peter Exp $ # $DragonFly: src/usr.sbin/rpc.lockd/Makefile,v 1.2 2003/06/17 04:30:02 dillon Exp $ -PROG = rpc.lockd -SRCS = nlm_prot_svc.c nlm_prot_clnt.c nlm_prot.h lockd.c procs.c +PROG= rpc.lockd MAN= rpc.lockd.8 +MLINKS= rpc.lockd.8 lockd.8 +SRCS= nlm_prot_svc.c lockd.c lock_proc.c lockd_lock.c -MAN8 = rpc.lockd.8 +CFLAGS+= -I. -I${DESTDIR}/usr/include/rpcsvc +#WARNS?= 2 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +DPADD= ${LIBRPCSVC} ${LIBUTIL} +LDADD= -lrpcsvc -lutil -CFLAGS+= -I. +CLEANFILES= nlm_prot_svc.c nlm_prot.h test -CLEANFILES= nlm_prot_svc.c nlm_prot.h nlm_prot_clnt.c \ - klm_prot_svc.c klm_prot.h - -NLMRPCSRC= ${DESTDIR}/usr/include/rpcsvc/nlm_prot.x -KLMRPCSRC= ${DESTDIR}/usr/include/rpcsvc/klm_prot.x +RPCSRC= ${DESTDIR}/usr/include/rpcsvc/nlm_prot.x RPCGEN= rpcgen -L -C -nlm_prot_clnt.c: ${NLMRPCSRC} - ${RPCGEN} -l -o ${.TARGET} ${NLMRPCSRC} - -nlm_prot_svc.c: ${NLMRPCSRC} - ${RPCGEN} -m -o ${.TARGET} ${NLMRPCSRC} - -nlm_prot.h: ${NLMRPCSRC} - ${RPCGEN} -h -o ${.TARGET} ${NLMRPCSRC} - -klm_prot_svc.c: ${KLMRPCSRC} - ${RPCGEN} -m -o ${.TARGET} ${KLMRPCSRC} +nlm_prot_svc.c: ${RPCSRC} + ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} -klm_prot.h: ${KLMRPCSRC} - ${RPCGEN} -h -o ${.TARGET} ${KLMRPCSRC} +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 diff --git a/usr.sbin/rpc.lockd/lock_proc.c b/usr.sbin/rpc.lockd/lock_proc.c new file mode 100644 index 0000000000..4dc643a65f --- /dev/null +++ b/usr.sbin/rpc.lockd/lock_proc.c @@ -0,0 +1,1227 @@ +/* + * 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. + * + * $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ + * $FreeBSD: src/usr.sbin/rpc.lockd/lock_proc.c,v 1.1 2001/03/19 12:50:09 alfred Exp $ + * $DragonFly$ + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "lockd.h" +#include +#include "lockd_lock.h" + + +#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ +#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ + +#define getrpcaddr(rqstp) (struct sockaddr *)(svc_getrpccaller((rqstp)->rq_xprt)->buf) + +static void log_from_addr(const char *, struct svc_req *); +static void log_netobj(netobj *obj); +static int addrcmp(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(const 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 rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE]; +static int clnt_cache_next_to_use = 0; + +static int +addrcmp(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(struct sockaddr *host_addr, rpcvers_t vers) +{ + CLIENT *client; + struct timeval retry_time, time_now; + int error, i; + const char *netid; + struct netconfig *nconf; + char host[NI_MAXHOST]; + uid_t old_euid; + int clnt_fd; + + 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) && clnt_cache_vers[i] == vers) { + /* Found it! */ + if (debug_level > 3) + syslog(LOG_DEBUG, "Found CLIENT* in cache"); + return (client); + } + } + + if (debug_level > 3) + syslog(LOG_DEBUG, "CLIENT* not found in cache, creating"); + + /* 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. + */ + error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host, + NULL, 0, NI_NUMERICHOST); + if (error != 0) { + syslog(LOG_ERR, "unable to get name string for caller: %s", + gai_strerror(error)); + 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; + } + + /* Get the FD of the client, for bindresvport. */ + clnt_control(client, CLGET_FD, &clnt_fd); + + /* Regain root privileges, for bindresvport. */ + old_euid = geteuid(); + seteuid(0); + + /* + * Bind the client FD to a reserved port. + * Some NFS servers reject any NLM request from a non-reserved port. + */ + bindresvport(clnt_fd, NULL); + + /* Drop root privileges again. */ + seteuid(old_euid); + + /* 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_vers[clnt_cache_next_to_use] = vers; + 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(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, (xdrproc_t)xdr_nlm_res, result, + (xdrproc_t)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(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, + (xdrproc_t)xdr_nlm4_res, result, + (xdrproc_t)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(struct nlm_lock *, struct nlm4_lock *); +static void +nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4) +{ + arg4->caller_name = arg->caller_name; + arg4->fh = arg->fh; + arg4->oh = arg->oh; + arg4->svid = arg->svid; + 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(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(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, + (xdrproc_t)xdr_nlm_testres, &res, + (xdrproc_t)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(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(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, getrpcaddr(rqstp)); + + return (NULL); +} + +/* nlm_cancel -------------------------------------------------------------- */ +/* + * Purpose: Cancel a blocked lock request + * Returns: granted or denied + * Notes: + */ +nlm_res * +nlm_cancel_1_svc(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(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, getrpcaddr(rqstp)); + 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(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(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, getrpcaddr(rqstp)); + 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(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(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(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(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(nlm_res *arg __unused, 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(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(nlm_res *arg __unused, 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(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(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(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(nlm_notify *arg __unused, 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(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(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, + (xdrproc_t)xdr_nlm4_testres, &res, + (xdrproc_t)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(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(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, getrpcaddr(rqstp)); + + return (NULL); +} + +/* nlm_cancel -------------------------------------------------------------- */ +/* + * Purpose: Cancel a blocked lock request + * Returns: granted or denied + * Notes: + */ +nlm4_res * +nlm4_cancel_4_svc(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(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, getrpcaddr(rqstp)); + 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(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(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, getrpcaddr(rqstp)); + 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(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(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(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(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(nlm4_res *arg __unused, 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(nlm4_res *arg __unused, 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(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(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(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(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(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(struct nlm_sm_status *arg, struct svc_req *rqstp __unused) +{ + 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 389ef664ca..17f13cd27a 100644 --- a/usr.sbin/rpc.lockd/lockd.c +++ b/usr.sbin/rpc.lockd/lockd.c @@ -29,82 +29,489 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.lockd/lockd.c,v 1.5.2.1 2001/08/01 06:39:36 alfred Exp $ + * $NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $ + * $FreeBSD: src/usr.sbin/rpc.lockd/lockd.c,v 1.6 2001/03/19 12:50:09 alfred Exp $ * $DragonFly: src/usr.sbin/rpc.lockd/lockd.c,v 1.5 2005/11/25 00:32:49 swildner Exp $ */ -/* 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 */ +/* + * 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 + */ + +#include +#include + +#include +#include #include +#include #include +#include +#include +#include #include +#include +#include +#include +#include + #include -#include +#include +#include + #include "lockd.h" +#include + +int debug_level = 0; /* 0 = no debugging syslog() calls */ +int _rpcsvcdirty = 0; -void nlm_prog_1(struct svc_req *, SVCXPRT *); -void nlm_prog_3(struct svc_req *, SVCXPRT *); -void nlm_prog_4(struct svc_req *, SVCXPRT *); -static void usage(void); +int grace_expired; +char **hosts, *svcport_str = NULL; +int nhosts = 0; +int xcreated = 0; -int debug_level = 0; /* Zero means no debugging syslog() calls */ +#ifndef IPPORT_MAX +#define IPPORT_MAX 65535 +#endif + +void create_service(struct netconfig *); + +void nlm_prog_0(struct svc_req *, SVCXPRT *); +void nlm_prog_1(struct svc_req *, SVCXPRT *); +void nlm_prog_3(struct svc_req *, SVCXPRT *); +void nlm_prog_4(struct svc_req *, SVCXPRT *); +void out_of_mem(void); + +static void usage(void); + +void sigalarm_handler(void); int main(int argc, char **argv) { - 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; - } - - pmap_unset(NLM_PROG, NLM_VERS); - pmap_unset(NLM_PROG, NLM_VERSX); - pmap_unset(NLM_PROG, NLM4_VERS); - - 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)"); - if (!svc_register(transp, NLM_PROG, NLM4_VERS, nlm_prog_4, IPPROTO_UDP)) - errx(1, "unable to register (NLM_PROG, NLM4_VERS, 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)"); - if (!svc_register(transp, NLM_PROG, NLM4_VERS, nlm_prog_4, IPPROTO_TCP)) - errx(1, "unable to register (NLM_PROG, NLM4_VERS, 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); + int ch, i, s; + void *nc_handle; + char *endptr, **hosts_bak; + struct sigaction sigalarm; + int grace_period = 30; + struct netconfig *nconf; + int have_v6 = 1; + int maxrec = RPC_MAXDATASIZE; + in_port_t svcport = 0; + + while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-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; + case 'h': + ++nhosts; + hosts_bak = hosts; + hosts_bak = realloc(hosts, nhosts * sizeof(char *)); + if (hosts_bak == NULL) { + if (hosts != NULL) { + for (i = 0; i < nhosts; i++) + free(hosts[i]); + free(hosts); + out_of_mem(); + } + } + hosts = hosts_bak; + hosts[nhosts - 1] = strdup(optarg); + if (hosts[nhosts - 1] == NULL) { + for (i = 0; i < (nhosts - 1); i++) + free(hosts[i]); + free(hosts); + out_of_mem(); + } + break; + case 'p': + endptr = NULL; + svcport = (in_port_t)strtoul(optarg, &endptr, 10); + if (endptr == NULL || *endptr != '\0' || + svcport == 0 || svcport >= IPPORT_MAX) + usage(); + svcport_str = strdup(optarg); + break; + default: + case '?': + usage(); + /* NOTREACHED */ + } + } + if (geteuid()) { /* This command allowed only to root */ + fprintf(stderr, "Sorry. You are not superuser\n"); + exit(1); + } + + rpcb_unset(NLM_PROG, NLM_SM, NULL); + rpcb_unset(NLM_PROG, NLM_VERS, NULL); + rpcb_unset(NLM_PROG, NLM_VERSX, NULL); + rpcb_unset(NLM_PROG, NLM_VERS4, NULL); + + /* + * Check if IPv6 support is present. + */ + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) + have_v6 = 0; + else + close(s); + + rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); + + /* + * If no hosts were specified, add a wildcard entry to bind to + * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the + * list. + */ + if (nhosts == 0) { + hosts = malloc(sizeof(char**)); + if (hosts == NULL) + out_of_mem(); + + hosts[0] = "*"; + nhosts = 1; + } else { + hosts_bak = hosts; + if (have_v6) { + hosts_bak = realloc(hosts, (nhosts + 2) * + sizeof(char *)); + if (hosts_bak == NULL) { + for (i = 0; i < nhosts; i++) + free(hosts[i]); + free(hosts); + out_of_mem(); + } else + hosts = hosts_bak; + + nhosts += 2; + hosts[nhosts - 2] = "::1"; + } else { + hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); + if (hosts_bak == NULL) { + for (i = 0; i < nhosts; i++) + free(hosts[i]); + + free(hosts); + out_of_mem(); + } else { + nhosts += 1; + hosts = hosts_bak; + } + } + hosts[nhosts - 1] = "127.0.0.1"; + } + + nc_handle = setnetconfig(); + while ((nconf = getnetconfig(nc_handle))) { + /* We want to listen only on udp6, tcp6, udp, tcp transports */ + if (nconf->nc_flag & NC_VISIBLE) { + /* Skip if there's no IPv6 support */ + if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { + /* DO NOTHING */ + } else { + create_service(nconf); + } + } + } + endnetconfig(nc_handle); + + /* + * 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, debug_level > 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"); + + sigalarm.sa_handler = (sig_t) 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; + alarm(grace_period); + + svc_run(); /* Should never return */ + exit(1); +} + +/* + * This routine creates and binds sockets on the appropriate + * addresses. It gets called one time for each transport and + * registrates the service with rpcbind on that trasport. + */ +void +create_service(struct netconfig *nconf) +{ + struct addrinfo hints, *res = NULL; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct __rpc_sockinfo si; + struct netbuf servaddr; + SVCXPRT *transp = NULL; + int aicode; + int fd; + int nhostsbak; + int r; + int registered = 0; + u_int32_t host_addr[4]; /* IPv4 or IPv6 */ + + if ((nconf->nc_semantics != NC_TPI_CLTS) && + (nconf->nc_semantics != NC_TPI_COTS) && + (nconf->nc_semantics != NC_TPI_COTS_ORD)) + return; /* not my type */ + + /* + * XXX - using RPC library internal functions. + */ + if (!__rpc_nconf2sockinfo(nconf, &si)) { + syslog(LOG_ERR, "cannot get information for %s", + nconf->nc_netid); + return; + } + + /* Get rpc.statd'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; + + /* + * Bind to specific IPs if asked to + */ + nhostsbak = nhosts; + while (nhostsbak > 0) { + --nhostsbak; + + /* + * XXX - using RPC library internal functions. + */ + if ((fd = __rpc_nconf2fd(nconf)) < 0) { + syslog(LOG_ERR, "cannot create socket for %s", + nconf->nc_netid); + continue; + } + + switch (hints.ai_family) { + case AF_INET: + if (inet_pton(AF_INET, hosts[nhostsbak], + host_addr) == 1) { + hints.ai_flags &= AI_NUMERICHOST; + } else { + /* + * Skip if we have an AF_INET6 address. + */ + if (inet_pton(AF_INET6, hosts[nhostsbak], + host_addr) == 1) { + close(fd); + continue; + } + } + break; + case AF_INET6: + if (inet_pton(AF_INET6, hosts[nhostsbak], + host_addr) == 1) { + hints.ai_flags &= AI_NUMERICHOST; + } else { + /* + * Skip if we have an AF_INET address. + */ + if (inet_pton(AF_INET, hosts[nhostsbak], + host_addr) == 1) { + close(fd); + continue; + } + } + break; + default: + break; + } + + /* + * If no hosts were specified, just bind to INADDR_ANY + */ + if (strcmp("*", hosts[nhostsbak]) == 0) { + if (svcport_str == NULL) { + res = malloc(sizeof(struct addrinfo)); + if (res == NULL) + out_of_mem(); + res->ai_flags = hints.ai_flags; + res->ai_family = hints.ai_family; + res->ai_protocol = hints.ai_protocol; + switch (res->ai_family) { + case AF_INET: + sin = malloc(sizeof(struct sockaddr_in)); + if (sin == NULL) + out_of_mem(); + sin->sin_family = AF_INET; + sin->sin_port = htons(0); + sin->sin_addr.s_addr = htonl(INADDR_ANY); + res->ai_addr = (struct sockaddr*) sin; + res->ai_addrlen = (socklen_t) + sizeof(res->ai_addr); + break; + case AF_INET6: + sin6 = malloc(sizeof(struct sockaddr_in6)); + if (sin6 == NULL) + out_of_mem(); + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(0); + sin6->sin6_addr = in6addr_any; + res->ai_addr = (struct sockaddr*) sin6; + res->ai_addrlen = (socklen_t) sizeof(res->ai_addr); + break; + default: + break; + } + } else { + if ((aicode = getaddrinfo(NULL, svcport_str, + &hints, &res)) != 0) { + syslog(LOG_ERR, + "cannot get local address for %s: %s", + nconf->nc_netid, + gai_strerror(aicode)); + continue; + } + } + } else { + if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str, + &hints, &res)) != 0) { + syslog(LOG_ERR, + "cannot get local address for %s: %s", + nconf->nc_netid, gai_strerror(aicode)); + continue; + } + } + + r = bindresvport_sa(fd, res->ai_addr); + if (r != 0) { + syslog(LOG_ERR, "bindresvport_sa: %m"); + exit(1); + } + + transp = svc_tli_create(fd, nconf, NULL, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); + + if (transp != (SVCXPRT *) NULL) { + if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0, + NULL)) + syslog(LOG_ERR, + "can't register %s NLM_PROG, NLM_SM service", + nconf->nc_netid); + + if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1, + NULL)) + syslog(LOG_ERR, + "can't register %s NLM_PROG, NLM_VERS service", + nconf->nc_netid); + + if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, + NULL)) + syslog(LOG_ERR, + "can't register %s NLM_PROG, NLM_VERSX service", + nconf->nc_netid); + + if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, + NULL)) + syslog(LOG_ERR, + "can't register %s NLM_PROG, NLM_VERS4 service", + nconf->nc_netid); + + } else + syslog(LOG_WARNING, "can't create %s services", + nconf->nc_netid); + + if (registered == 0) { + registered = 1; + 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 (svcport_str == NULL) { + svcport_str = malloc(NI_MAXSERV * sizeof(char)); + if (svcport_str == NULL) + out_of_mem(); + + if (getnameinfo(res->ai_addr, + res->ai_addr->sa_len, NULL, NI_MAXHOST, + svcport_str, NI_MAXSERV * sizeof(char), + NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "Cannot get port number"); + } + + if((aicode = getaddrinfo(NULL, svcport_str, &hints, + &res)) != 0) { + syslog(LOG_ERR, "cannot get local address: %s", + gai_strerror(aicode)); + exit(1); + } + + servaddr.buf = malloc(res->ai_addrlen); + memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen); + servaddr.len = res->ai_addrlen; + + rpcb_set(NLM_PROG, NLM_SM, nconf, &servaddr); + rpcb_set(NLM_PROG, NLM_VERS, nconf, &servaddr); + rpcb_set(NLM_PROG, NLM_VERSX, nconf, &servaddr); + rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr); + + xcreated++; + freeaddrinfo(res); + } + } /* end while */ +} + +void +sigalarm_handler(void) +{ + + grace_expired = 1; } static void usage(void) { - fprintf(stderr, "usage: rpc.lockd [-d [debuglevel]]\n"); - exit(1); + errx(1, "usage: rpc.lockd [-d ]" + " [-g ] [-h ] [-p ]"); +} + +/* + * Out of memory, fatal + */ +void +out_of_mem(void) +{ + syslog(LOG_ERR, "out of memory"); + exit(2); } diff --git a/usr.sbin/rpc.lockd/lockd.h b/usr.sbin/rpc.lockd/lockd.h index 39586bfd77..d8faf95908 100644 --- a/usr.sbin/rpc.lockd/lockd.h +++ b/usr.sbin/rpc.lockd/lockd.h @@ -29,16 +29,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $NetBSD: lockd.h,v 1.2 2000/06/07 14:34:40 bouyer Exp $ + * $FreeBSD: src/usr.sbin/rpc.lockd/lockd.h,v 1.3 2001/03/19 12:50:09 alfred Exp $ + * $DragonFly$ */ - - -#include -#include -#include -#include /* 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; diff --git a/usr.sbin/rpc.lockd/lockd_lock.c b/usr.sbin/rpc.lockd/lockd_lock.c new file mode 100644 index 0000000000..b33ab5a8e8 --- /dev/null +++ b/usr.sbin/rpc.lockd/lockd_lock.c @@ -0,0 +1,743 @@ +/* + * 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. + * + * $NetBSD: lockd_lock.c,v 1.5 2000/11/21 03:47:41 enami Exp $ + * $FreeBSD: src/usr.sbin/rpc.lockd/lockd_lock.c,v 1.1 2001/03/19 12:50:09 alfred Exp $ + * $DragonFly$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(struct file_lock *); +enum nlm_stats do_lock(struct file_lock *, int); +enum nlm_stats do_unlock(struct file_lock *); +void send_granted(struct file_lock *, int); +void siglock(void); +void sigunlock(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(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(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(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(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(struct file_lock *fl) +{ + free(fl->client.oh.n_bytes); + free(fl->client_cookie.n_bytes); + free(fl); +} + +void +sigchild_handler(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(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(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(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(void) +{ + 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(void) +{ + 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(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(const 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, "unknown 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 0000000000..823fe1056a --- /dev/null +++ b/usr.sbin/rpc.lockd/lockd_lock.h @@ -0,0 +1,23 @@ +/* $NetBSD: lockd_lock.h,v 1.2 2000/06/09 14:00:54 fvdl Exp $ */ +/* $FreeBSD: src/usr.sbin/rpc.lockd/lockd_lock.h,v 1.4 2002/03/21 22:52:45 alfred Exp $ */ +/* $DragonFly$ */ + +/* Headers and function declarations for file-locking utilities */ + +struct nlm4_holder *testlock(struct nlm4_lock *, int); +enum nlm_stats getlock(nlm4_lockargs *, struct svc_req *, const int); +enum nlm_stats unlock(nlm4_lock *, const int); +int lock_answer(int, netobj *, int, int *, int); + +void notify(const char *, const 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(int, nlm_res *, struct sockaddr *); +void transmit4_result(int, nlm4_res *, struct sockaddr *); +CLIENT *get_client(struct sockaddr *, rpcvers_t); diff --git a/usr.sbin/rpc.lockd/procs.c b/usr.sbin/rpc.lockd/procs.c deleted file mode 100644 index dc3e5f2535..0000000000 --- a/usr.sbin/rpc.lockd/procs.c +++ /dev/null @@ -1,865 +0,0 @@ -/* - * 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. - * - * $FreeBSD: src/usr.sbin/rpc.lockd/procs.c,v 1.4.2.2 2001/08/01 06:39:36 alfred Exp $ - * $DragonFly: src/usr.sbin/rpc.lockd/procs.c,v 1.3 2005/11/25 00:32:49 swildner Exp $ - */ - -#include -#include "lockd.h" - -#include /* for MAXHOSTNAMELEN */ -#include -#include -#include -#include - - -#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ -#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ - -#if 0 -#undef LOG_DEBUG -#undef LOG_ERR -#define LOG_DEBUG stderr -#define LOG_ERR stderr -#define syslog fprintf -#endif - -/* 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(char *fun_name, struct svc_req *req) -{ - struct sockaddr_in *addr; - struct hostent *host; - char hostname_buf[40]; - - addr = svc_getcaller(req->rq_xprt); - host = gethostbyaddr(&(addr->sin_addr), addr->sin_len, AF_INET); - if (host) - { - strncpy(hostname_buf, host->h_name, sizeof(hostname_buf)); - hostname_buf[sizeof(hostname_buf) -1] = '\0'; - } - else /* No hostname available - print raw address */ - { - strcpy(hostname_buf, inet_ntoa(addr->sin_addr)); - } - - 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 in_addr clnt_cache_addr[CLIENT_CACHE_SIZE]; -static int clnt_cache_next_to_use = 0; - -static CLIENT * -get_client(struct sockaddr_in *host_addr) -{ - CLIENT *client; - int sock_no; - struct timeval retry_time, time_now; - int i; - - 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 && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr, - sizeof(struct in_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; - } - - /* Create the new client handle */ - - sock_no = RPC_ANYSOCK; - retry_time.tv_sec = 5; - retry_time.tv_usec = 0; - host_addr->sin_port = 0; /* Force consultation with portmapper */ - client = clntudp_create(host_addr, NLM_PROG, NLM_VERS, retry_time, &sock_no); - if (!client) - { - syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create")); - syslog(LOG_ERR, "Unable to return result to %s", - inet_ntoa(host_addr->sin_addr)); - return NULL; - } - - /* Success - update the cache entry */ - clnt_cache_ptr[clnt_cache_next_to_use] = client; - clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr; - 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, &retry_time); - - if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s", - inet_ntoa(host_addr->sin_addr)); - 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 -*/ - -static void -transmit_result(int opcode, void *result, struct svc_req *req) -{ - static char dummy; - struct sockaddr_in *addr; - CLIENT *cli; - int success; - struct timeval timeo; - - addr = svc_getcaller(req->rq_xprt); - if ((cli = get_client(addr))) - { - 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", success); - } -} - -/* ------------------------------------------------------------------------- */ -/* - 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(nlm_testargs *arg, struct svc_req *rqstp) -{ - static nlm_testres res; - if (debug_level) log_from_addr("nlm_test", rqstp); - - /* 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; - res.stat.stat = nlm_granted; - return (&res); -} - -nlm4_testres * -nlmproc4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) -{ - static nlm4_testres res; - if (debug_level) log_from_addr("nlm_test", rqstp); - - /* 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; - res.stat.stat = nlm4_granted; - return (&res); -} - -void * -nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - nlm_testres res; - static char dummy; - struct sockaddr_in *addr; - CLIENT *cli; - int success; - struct timeval timeo; - - if (debug_level) log_from_addr("nlm_test_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - - /* nlm_test has different result type to the other operations, so */ - /* can't use transmit_result() in this case */ - addr = svc_getcaller(rqstp->rq_xprt); - if ((cli = get_client(addr))) - { - 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); -} - -void * -nlmproc4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) -{ - nlm4_testres res; - static char dummy; - struct sockaddr_in *addr; - CLIENT *cli; - int success; - struct timeval timeo; - - if (debug_level) log_from_addr("nlm_test_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm4_granted; - - /* nlm_test has different result type to the other operations, so */ - /* can't use transmit_result() in this case */ - addr = svc_getcaller(rqstp->rq_xprt); - if ((cli = get_client(addr))) - { - timeo.tv_sec = 0; /* No timeout - not expecting response */ - timeo.tv_usec = 0; - - success = clnt_call(cli, NLMPROC4_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(nlm_lockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - 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 = nlm_granted; - return (&res); -} - -nlm4_res * -nlmproc4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - - 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 = nlm4_granted; - return (&res); -} - -void * -nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - - if (debug_level) log_from_addr("nlm_lock_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - transmit_result(NLM_LOCK_RES, &res, rqstp); - - return (NULL); -} - -void * -nlmproc4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - - if (debug_level) log_from_addr("nlm_lock_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm4_granted; - transmit_result(NLMPROC4_LOCK_RES, &res, rqstp); - - return (NULL); -} - - -/* nlm_cancel -------------------------------------------------------------- */ -/* - Purpose: Cancel a blocked lock request - Returns: granted or denied - Notes: -*/ - -nlm_res * -nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - 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 = nlm_denied; - return (&res); -} - -nlm4_res * -nlmproc4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - 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 = nlm4_denied; - return (&res); -} - -void * -nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - 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 = nlm_denied; - transmit_result(NLM_CANCEL_RES, &res, rqstp); - return (NULL); -} - -void * -nlmproc4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - 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 = nlm4_denied; - transmit_result(NLMPROC4_CANCEL_RES, &res, rqstp); - 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(nlm_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_unlock", rqstp); - - res.stat.stat= nlm_granted; - res.cookie = arg->cookie; - - return (&res); -} - -nlm4_res * -nlmproc4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - if (debug_level) log_from_addr("nlm_unlock", rqstp); - - res.stat.stat= nlm4_granted; - res.cookie = arg->cookie; - - return (&res); -} - -void * -nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_unlock_msg", rqstp); - - res.stat.stat = nlm_granted; - res.cookie = arg->cookie; - - transmit_result(NLM_UNLOCK_RES, &res, rqstp); - return (NULL); -} - -void * -nlmproc4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm4_res res; - if (debug_level) log_from_addr("nlm_unlock_msg", rqstp); - - res.stat.stat = nlm4_granted; - res.cookie = arg->cookie; - - transmit_result(NLMPROC4_UNLOCK_RES, &res, rqstp); - 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(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); -} - -nlm4_res * -nlmproc4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) -{ - static nlm4_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 = nlm4_granted; - return (&res); -} - -void * -nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - 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, rqstp); - return (NULL); -} - -void * -nlmproc4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) -{ - nlm4_res res; - if (debug_level) log_from_addr("nlm_granted_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm4_granted; - transmit_result(NLMPROC4_GRANTED_RES, &res, rqstp); - return (NULL); -} - -/* nlm_test_res ------------------------------------------------------------ */ -/* - Purpose: Accept result from earlier nlm_test_msg() call - Returns: Nothing -*/ - -void * -nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_test_res", rqstp); - return (NULL); -} - -void * -nlmproc4_test_res_4_svc(nlm4_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(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_lock_res", rqstp); - - return (NULL); -} - -void * -nlmproc4_lock_res_4_svc(nlm4_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(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_cancel_res", rqstp); - return (NULL); -} - -void * -nlmproc4_cancel_res_4_svc(nlm4_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(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_unlock_res", rqstp); - return (NULL); -} - -void * -nlmproc4_unlock_res_4_svc(nlm4_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(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_granted_res", rqstp); - return (NULL); -} - -void * -nlmproc4_granted_res_4_svc(nlm4_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(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); -} - -nlm4_shareres * -nlmproc4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp) -{ - static nlm4_shareres res; - if (debug_level) log_from_addr("nlm_share", rqstp); - - res.cookie = arg->cookie; - res.stat = nlm4_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(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); -} - -nlm4_shareres * -nlmproc4_unshare_4_svc(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); -} - -/* 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(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); -} - -nlm4_res * -nlmproc4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) -{ - static nlm4_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 = nlm4_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(nlm_notify *arg, struct svc_req *rqstp) -{ - static char dummy; - - if (debug_level) log_from_addr("nlm_free_all", rqstp); - return (&dummy); -} - -void * -nlmproc4_free_all_4_svc(nlm4_notify *arg, struct svc_req *rqstp) -{ - static char dummy; - - if (debug_level) log_from_addr("nlm_free_all", rqstp); - return (&dummy); -} - -void * -nlmproc4_null_4_svc(void *arg, struct svc_req *rqstp) -{ - static char dummy; - - if (debug_level) log_from_addr("nlm_free_all", rqstp); - return (&dummy); -} - - diff --git a/usr.sbin/rpc.lockd/rpc.lockd.8 b/usr.sbin/rpc.lockd/rpc.lockd.8 index cdfcfba3c7..650d320e63 100644 --- a/usr.sbin/rpc.lockd/rpc.lockd.8 +++ b/usr.sbin/rpc.lockd/rpc.lockd.8 @@ -1,4 +1,4 @@ -.\" -*- nroff -*- +.\" $NetBSD: rpc.lockd.8,v 1.5 2000/06/09 18:51:47 cgd Exp $ .\" .\" Copyright (c) 1995 A.R.Gordon, andrew.gordon@net-tel.co.uk .\" All rights reserved. @@ -31,10 +31,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/rpc.lockd/rpc.lockd.8,v 1.8.2.1 2000/12/08 15:28:49 ru Exp $ +.\" $FreeBSD: src/usr.sbin/rpc.lockd/rpc.lockd.8,v 1.18 2007/11/02 14:51:53 matteo Exp $ .\" $DragonFly: src/usr.sbin/rpc.lockd/rpc.lockd.8,v 1.4 2006/02/17 19:40:23 swildner Exp $ .\" -.Dd September 24, 1995 +.Dd November 2, 2007 .Dt RPC.LOCKD 8 .Os .Sh NAME @@ -42,34 +42,89 @@ .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 +.Op Fl h Ar bindip +.Op Fl p Ar port .Sh DESCRIPTION -.Nm Rpc.lockd -is a daemon which provides file- and record-locking services in an NFS -environment. +The +.Nm +utility 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. +.It Fl h Ar bindip +Specify specific IP addresses to bind to. +This option may be specified multiple times. +If no +.Fl h +option is specified, +.Nm +will bind to +.Dv INADDR_ANY . +Note that when specifying IP addresses with +.Fl h , +.Nm +will automatically add +.Li 127.0.0.1 +and if IPv6 is enabled, +.Li ::1 +to the list. +.It Fl p +The +.Fl p +option allow to force the daemon to bind to the specified +.Ar port , +for both AF_INET and AF_INET6 address families. .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 +utility 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 @@ -77,21 +132,28 @@ 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 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. .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 .Dx fileserver, but there is currently no means for a .Dx 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. diff --git a/usr.sbin/rpc.lockd/test.c b/usr.sbin/rpc.lockd/test.c index 67be361430..5add893c82 100644 --- a/usr.sbin/rpc.lockd/test.c +++ b/usr.sbin/rpc.lockd/test.c @@ -1,7 +1,8 @@ /* * @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC - * $FreeBSD: src/usr.sbin/rpc.lockd/test.c,v 1.4.2.1 2001/08/01 06:39:36 alfred Exp $ + * $NetBSD: test.c,v 1.2 1997/10/18 04:01:21 lukem Exp $ + * $FreeBSD: src/usr.sbin/rpc.lockd/test.c,v 1.5 2001/03/19 12:50:09 alfred Exp $ * $DragonFly: src/usr.sbin/rpc.lockd/test.c,v 1.3 2005/11/25 00:32:49 swildner Exp $ */ @@ -265,70 +266,59 @@ nlm_free_all_3(nlm_notify *argp, CLIENT *clnt) int main(int argc, char **argv) { - CLIENT *cli; - nlm_res res_block; - nlm_res *out; - nlm_lockargs arg; - struct timeval tim; - - if (argc != 2) - { - printf("usage: %s \n", argv[0]); - exit(1); - } - - - 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.umntall/rpc.umntall.8 b/usr.sbin/rpc.umntall/rpc.umntall.8 index c1f05b29e1..1a0b50ef72 100644 --- a/usr.sbin/rpc.umntall/rpc.umntall.8 +++ b/usr.sbin/rpc.umntall/rpc.umntall.8 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/rpc.umntall/rpc.umntall.8,v 1.6.2.3 2003/03/11 22:31:32 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/rpc.umntall/rpc.umntall.8,v 1.12 2005/02/13 22:25:32 ru Exp $ .\" $DragonFly: src/usr.sbin/rpc.umntall/rpc.umntall.8,v 1.6 2008/11/26 15:27:24 swildner Exp $ .\" .Dd November 17, 1999 @@ -39,7 +39,6 @@ .Op Fl k .Op Fl p Ar remotepath .Op Fl v -.Op Fl f .Sh DESCRIPTION The .Nm @@ -97,7 +96,7 @@ existing mount entries. Useful during startup of the system. It may be possible that there are already mounted NFS file systems, so calling -RPC UMOUNT isn't a good idea. +RPC UMOUNT is not a good idea. This is the case if the user has rebooted to 'single user mode' and starts up the system again. .It Fl p Ar path @@ -109,14 +108,6 @@ option. .It Fl v Verbose, additional information is printed for each processed mounttab entry. -.It Fl f -Fast mode. -The resolver timeout is reduced to 4 seconds and the -.Fn pmap_getport -timeout is reduced from 60 seconds to 3. -This option is used when -.Nm -is used in the boot sequence to facilitate booting. .El .Sh FILES .Bl -tag -width /var/db/mounttab -compact diff --git a/usr.sbin/rpc.umntall/rpc.umntall.c b/usr.sbin/rpc.umntall/rpc.umntall.c index aa16c32b7b..d7c4a0eef5 100644 --- a/usr.sbin/rpc.umntall/rpc.umntall.c +++ b/usr.sbin/rpc.umntall/rpc.umntall.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.umntall/rpc.umntall.c,v 1.3.2.1 2001/12/13 01:27:20 iedowse Exp $ + * $FreeBSD: src/usr.sbin/rpc.umntall/rpc.umntall.c,v 1.13 2005/05/27 00:05:16 mux Exp $ * $DragonFly: src/usr.sbin/rpc.umntall/rpc.umntall.c,v 1.7 2008/11/12 21:44:59 swildner Exp $ */ @@ -52,7 +52,6 @@ static int do_umount (char *, char *); static int do_umntall (char *); static int is_mounted (char *, char *); static void usage (void); -static struct hostent *gethostbyname_quick(const char *name); int xdr_dir (XDR *, char *); @@ -66,7 +65,7 @@ main(int argc, char **argv) { expire = 0; host = path = NULL; success = keep = verbose = 0; - while ((ch = getopt(argc, argv, "h:kp:vfe:")) != -1) + while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1) switch (ch) { case 'h': host = optarg; @@ -83,9 +82,6 @@ main(int argc, char **argv) { case 'v': verbose = 1; break; - case 'f': - fastopt = 1; - break; case '?': usage(); default: @@ -176,36 +172,21 @@ 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 timeval try; CLIENT *clp; - if ((hp = gethostbyname_quick(hostname)) == NULL) { - warnx("gethostbyname(%s) failed", hostname); - return (0); - } - 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, - (int)sizeof(saddr.sin_addr))); - pertry.tv_sec = 3; - pertry.tv_usec = 0; - if (fastopt) - pmap_getport_timeout(NULL, &pertry); - so = RPC_ANYSOCK; - clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so); + try.tv_sec = 3; + try.tv_usec = 0; + clp = clnt_create_timed(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp", + &try); if (clp == NULL) { warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT")); return (0); } clp->cl_auth = authunix_create_default(); - try.tv_sec = 3; - try.tv_usec = 0; - clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0, - xdr_void, (caddr_t)0, try); + clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, + (xdrproc_t)xdr_void, (caddr_t)0, + (xdrproc_t)xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMNTALL")); auth_destroy(clp->cl_auth); @@ -219,36 +200,20 @@ 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 timeval try; CLIENT *clp; - int so; - if ((hp = gethostbyname_quick(hostname)) == NULL) { - warnx("gethostbyname(%s) failed", hostname); - return (0); - } - 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, - (int)sizeof(saddr.sin_addr))); - pertry.tv_sec = 3; - pertry.tv_usec = 0; - if (fastopt) - pmap_getport_timeout(NULL, &pertry); - so = RPC_ANYSOCK; - clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so); + try.tv_sec = 3; + try.tv_usec = 0; + clp = clnt_create_timed(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp", + &try); if (clp == NULL) { warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT")); return (0); } - clp->cl_auth = authunix_create_default(); - try.tv_sec = 3; - try.tv_usec = 0; - clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp, - xdr_void, (caddr_t)0, try); + clp->cl_auth = authsys_create_default(); + clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, (xdrproc_t)xdr_dir, dirp, + (xdrproc_t)xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMOUNT")); auth_destroy(clp->cl_auth); @@ -286,32 +251,6 @@ is_mounted(char *hostname, char *dirp) { return (0); } -/* - * rpc.umntall is often called at boot. If the network or target host has - * issues we want to limit resolver stalls so rpc.umntall doesn't stall - * the boot sequence forever. - */ -struct hostent * -gethostbyname_quick(const char *name) -{ - struct hostent *he; - int save_retrans; - int save_retry; - - save_retrans = _res.retrans; - save_retry = _res.retry; - if (fastopt) { - _res.retrans = 1; - _res.retry = 2; - } - he = gethostbyname(name); - if (fastopt) { - _res.retrans = save_retrans; - _res.retry = save_retry; - } - return(he); -} - /* * xdr routines for mount rpc's */ diff --git a/usr.sbin/rpc.yppasswdd/Makefile b/usr.sbin/rpc.yppasswdd/Makefile index 79526796fe..79ff4de946 100644 --- a/usr.sbin/rpc.yppasswdd/Makefile +++ b/usr.sbin/rpc.yppasswdd/Makefile @@ -1,29 +1,32 @@ -# $FreeBSD: src/usr.sbin/rpc.yppasswdd/Makefile,v 1.13.2.3 2002/08/07 16:32:02 ru Exp $ +# $FreeBSD: src/usr.sbin/rpc.yppasswdd/Makefile,v 1.22 2007/11/20 02:07:30 jb Exp $ # $DragonFly: src/usr.sbin/rpc.yppasswdd/Makefile,v 1.2 2003/06/17 04:30:02 dillon Exp $ -PROG= rpc.yppasswdd -SRCS= pw_copy.c pw_util.c util.c yp_access.c yp_dblookup.c yp_dbwrite.c \ - yp_error.c yppasswdd_main.c yppasswdd_server.c ypxfr_misc.c ${GENSRCS} -GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_private.h yppasswd_private_svc.c \ - yppasswd_private_xdr.c yppasswd_svc.c - RPCDIR= ${DESTDIR}/usr/include/rpcsvc -.PATH: ${.CURDIR}/../../usr.sbin/ypserv ${.CURDIR}/../../usr.bin/chpass \ - ${.CURDIR}/../../libexec/ypxfr ${RPCDIR} +.PATH: ${.CURDIR}/../../usr.sbin/ypserv ${.CURDIR}/../../usr.bin/chpass \ + ${.CURDIR}/../../libexec/ypxfr ${RPCDIR} +PROG= rpc.yppasswdd +SCRIPTS=yppwupdate +SCRIPTSDIR= /usr/libexec MAN= rpc.yppasswdd.8 +SRCS= util.c yp_access.c yp_dblookup.c yp_dbwrite.c \ + yp_error.c yppasswdd_main.c yppasswdd_server.c ypxfr_misc.c ${GENSRCS} +GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_private.h yppasswd_private_svc.c \ + yppasswd_private_xdr.c yppasswd_svc.c -CFLAGS+= -I${.CURDIR}/../../usr.sbin/vipw -I${.CURDIR}/../../usr.sbin/ypserv \ - -I${.CURDIR}/../../libexec/ypxfr -I${.CURDIR}/../../usr.bin/chpass \ +WARNS?= 0 +CFLAGS+= -fno-strict-aliasing +CFLAGS+= -I${.CURDIR}/../../usr.sbin/vipw \ + -I${.CURDIR}/../../usr.sbin/ypserv \ + -I${.CURDIR}/../../libexec/ypxfr \ -I${.CURDIR} -I. - -DPADD= ${LIBRPCSVC} ${LIBCRYPT} -LDADD= -lrpcsvc -lcrypt +DPADD= ${LIBRPCSVC} ${LIBCRYPT} ${LIBUTIL} +LDADD= -lrpcsvc -lcrypt -lutil CLEANFILES= ${GENSRCS} -RPCGEN= rpcgen -I -C +RPCGEN= rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that # yppasswdd_main.c can see it. @@ -57,9 +60,4 @@ yppasswd_private_svc.c: yppasswd_private.x ${RPCGEN} -m ${.CURDIR}/yppasswd_private.x | \ sed s/"static int _rpcsvcstate = _IDLE"/"extern int _rpcsvcstate"/g > ${.TARGET} -afterinstall: - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ - ${.CURDIR}/yppwupdate \ - ${DESTDIR}/usr/libexec/yppwupdate - .include diff --git a/usr.sbin/rpc.yppasswdd/pw_copy.c b/usr.sbin/rpc.yppasswdd/pw_copy.c deleted file mode 100644 index b1e26abb45..0000000000 --- a/usr.sbin/rpc.yppasswdd/pw_copy.c +++ /dev/null @@ -1,147 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - * - * @(#)pw_copy.c 8.4 (Berkeley) 4/2/94 - * $FreeBSD: src/usr.sbin/rpc.yppasswdd/pw_copy.c,v 1.4.2.1 2000/07/12 11:09:40 davidn Exp $ - * $DragonFly: src/usr.sbin/rpc.yppasswdd/pw_copy.c,v 1.4 2005/11/25 00:32:49 swildner Exp $ - */ - -/* - * This module is used to copy the master password file, replacing a single - * record, by chpass(1) and passwd(1). - */ - -#include -#include -#include -#include - -#include -#include "yppasswdd_extern.h" - -int -pw_copy(int ffd, int tfd, struct passwd *pw) -{ - FILE *from, *to; - int done; - char *p, buf[8192]; - char uidstr[20]; - char gidstr[20]; - char chgstr[20]; - char expstr[20]; - - snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid); - snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid); - snprintf(chgstr, sizeof(chgstr), "%ld", pw->pw_change); - snprintf(expstr, sizeof(expstr), "%ld", pw->pw_expire); - - if (!(from = fdopen(ffd, "r"))) { - pw_error(passfile, 1, 1); - return(-1); - } - if (!(to = fdopen(tfd, "w"))) { - pw_error(tempname, 1, 1); - return(-1); - } - for (done = 0; fgets(buf, sizeof(buf), from);) { - if (!strchr(buf, '\n')) { - yp_error("%s: line too long", passfile); - pw_error(NULL, 0, 1); - goto err; - } - if (done) { - fprintf(to, "%s", buf); - if (ferror(to)) - goto err; - continue; - } - /* - * Just copy comments and blank lines - */ - p = buf + strspn(buf, " \t\n"); - if (*p == '\0' || *p == '#') { - fprintf(to, "%s", buf); - if (ferror(to)) - goto err; - continue; - } - if (!(p = strchr(buf, ':'))) { - yp_error("%s: corrupted entry", passfile); - pw_error(NULL, 0, 1); - goto err; - } - *p = '\0'; - if (strcmp(buf, pw->pw_name)) { - *p = ':'; - fprintf(to, "%s", buf); - if (ferror(to)) - goto err; - continue; - } - fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", - pw->pw_name, pw->pw_passwd, - pw->pw_fields & _PWF_UID ? uidstr : "", - pw->pw_fields & _PWF_GID ? gidstr : "", - pw->pw_class, - pw->pw_fields & _PWF_CHANGE ? chgstr : "", - pw->pw_fields & _PWF_EXPIRE ? expstr : "", - pw->pw_gecos, pw->pw_dir, pw->pw_shell); - done = 1; - if (ferror(to)) - goto err; - } - if (!done) { - if (allow_additions) { - fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", - pw->pw_name, pw->pw_passwd, - pw->pw_fields & _PWF_UID ? uidstr : "", - pw->pw_fields & _PWF_GID ? gidstr : "", - pw->pw_class, - pw->pw_fields & _PWF_CHANGE ? chgstr : "", - pw->pw_fields & _PWF_EXPIRE ? expstr : "", - pw->pw_gecos, pw->pw_dir, pw->pw_shell); - } else { - yp_error("user \"%s\" not found in %s -- \ -NIS maps and password file possibly out of sync", pw->pw_name, passfile); - goto err; - } - } - if (ferror(to)) { -err: pw_error(NULL, 1, 1); - fclose(to); - fclose(from); - return(-1); - } - fclose(to); - fclose(from); - return(0); -} diff --git a/usr.sbin/rpc.yppasswdd/pw_util.c b/usr.sbin/rpc.yppasswdd/pw_util.c deleted file mode 100644 index 4ab1914923..0000000000 --- a/usr.sbin/rpc.yppasswdd/pw_util.c +++ /dev/null @@ -1,177 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - * - * @(#)pw_util.c 8.3 (Berkeley) 4/2/94 - * $FreeBSD: src/usr.sbin/rpc.yppasswdd/pw_util.c,v 1.4.2.1 2002/02/15 00:46:57 des Exp $ - * $DragonFly: src/usr.sbin/rpc.yppasswdd/pw_util.c,v 1.4 2005/11/25 00:32:49 swildner Exp $ - */ - -/* - * This file is used by all the "password" programs; vipw(8), chpass(1), - * and passwd(1). - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "yppasswdd_extern.h" - -int pstat; -pid_t pid; - -void -pw_init(void) -{ - struct rlimit rlim; - - /* Unlimited resource limits. */ - rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CPU, &rlim); - setrlimit(RLIMIT_FSIZE, &rlim); - setrlimit(RLIMIT_STACK, &rlim); - setrlimit(RLIMIT_DATA, &rlim); - setrlimit(RLIMIT_RSS, &rlim); - - /* Don't drop core (not really necessary, but GP's). */ - rlim.rlim_cur = rlim.rlim_max = 0; - setrlimit(RLIMIT_CORE, &rlim); - - /* Turn off signals. */ - /* signal(SIGALRM, SIG_IGN); */ - signal(SIGHUP, SIG_IGN); - signal(SIGINT, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - - /* Create with exact permissions. */ - umask(0); -} - -static int lockfd; - -int -pw_lock(void) -{ - /* - * If the master password file doesn't exist, the system is hosed. - * Might as well try to build one. Set the close-on-exec bit so - * that users can't get at the encrypted passwords while editing. - * Open should allow flock'ing the file; see 4.4BSD. XXX - */ - lockfd = open(passfile, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) { - yp_error("%s: %s", passfile, strerror(errno)); - return (-1); - } - if (flock(lockfd, LOCK_EX|LOCK_NB)) { - yp_error("%s: the password db file is busy", passfile); - return(-1); - } - return (lockfd); -} - -int -pw_tmp(void) -{ - static char path[MAXPATHLEN]; - int fd; - char *p; - - sprintf(path,"%s",passfile); - if ((p = strrchr(path, '/'))) - ++p; - else - p = path; - strcpy(p, "pw.XXXXXX"); - if ((fd = mkstemp(path)) == -1) { - yp_error("%s: %s", path, strerror(errno)); - return(-1); - } - tempname = path; - return (fd); -} - -int -pw_mkdb(char *username) -{ - - yp_error("rebuilding the database..."); - fflush(stderr); - /* Temporarily turn off SIGCHLD catching */ - install_reaper(0); - if (!(pid = vfork())) { - if (!username) { - execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); - } else { - execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-u", username, - tempname, NULL); - } - pw_error(_PATH_PWD_MKDB, 1, 1); - return(-1); - } - /* Handle this ourselves. */ - reaper(-1); - /* Put the handler back. Foo. */ - install_reaper(1); - if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) { - return (-1); - } - yp_error("done"); - return (0); -} - -void -pw_error(char *name, int err, int eval) -{ - if (err && name != NULL) - yp_error("%s", name); - - yp_error("%s: unchanged", passfile); - unlink(tempname); -} diff --git a/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8 b/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8 index 1618846bcd..89d30ff30c 100644 --- a/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8 +++ b/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8,v 1.12.2.8 2003/03/11 22:31:32 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8,v 1.25 2005/02/13 23:45:53 ru Exp $ .\" $DragonFly: src/usr.sbin/rpc.yppasswdd/rpc.yppasswdd.8,v 1.4 2006/02/17 19:40:24 swildner Exp $ .\" .Dd February 8, 1996 @@ -84,7 +84,7 @@ the or .Xr ypchpass 1 commands. -(Some administrators don't want users to be able to change their +(Some administrators do not want users to be able to change their full name information or shells; the server can be invoked with option flags that disallow such changes.) When the server receives an update request, @@ -100,7 +100,7 @@ utility uses the same access control mechanism as .Xr ypserv 8 . ) .Pp The server then -checks the 'old' password supplied by the user to make sure it's +checks the 'old' password supplied by the user to make sure it is valid, then performs some sanity checks on the updated information (these include checking for embedded control characters, colons or invalid shells). Once it is satisfied that the update request is valid, the server modifies @@ -126,7 +126,8 @@ The super-user can modify any field in any user's master.passwd entry in any domain, and can do so without knowing the user's existing NIS password (when the server receives a request from the super-user, the password authentication -check is bypassed). Furthermore, if the server is invoked with the +check is bypassed). +Furthermore, if the server is invoked with the .Fl a flag, the super-user can even add new entries to the maps using .Xr ypchpass 1 . @@ -249,7 +250,7 @@ be either or .Pa /var/yp/master.passwd . The server will check for the latter file first and then use the former -if it can't find it. +if it cannot find it. .Pp Multi-domain mode is off by default since it can fail if there are duplicate or near-duplicate user entries in different domains. @@ -306,7 +307,7 @@ flag to .Nm disables the privileged port check so that it will work with .Xr yppasswd 1 -clients that don't use privileged ports. +clients that do not use privileged ports. This reduces security to a certain small degree, but it might be necessary in cases where it is not possible to change the client behavior. diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h index d1216cff35..4252e16d2a 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h @@ -29,20 +29,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h,v 1.9.2.1 2002/02/15 00:46:57 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h,v 1.14 2002/07/11 21:28:16 alfred Exp $ * $DragonFly: src/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h,v 1.4 2004/05/20 19:24:43 cpressey Exp $ */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "yp_extern.h" -#include "ypxfr_extern.h" +#ifndef _YPPASSWDD_EXTERN_H +#define _YPPASSWDD_EXTERN_H #ifndef YPLIBDIR #define YPLIBDIR "/usr/libexec/" @@ -59,18 +51,12 @@ extern char *yp_dir; extern char *progname; extern void do_master(void); extern void yppasswdprog_1(struct svc_req *, SVCXPRT *); -extern void master_yppasswdprog_1(struct svc_req *, SVCXPRT *); +extern void master_yppasswdprog_1(struct svc_req *, SVCXPRT *); extern void reaper(int); extern void install_reaper(int); -extern int pw_copy(int, int, struct passwd *); -extern int pw_lock(void); -extern int pw_mkdb(char *); -extern int pw_tmp(void); -extern void pw_init(void); extern char *ok_shell(char *); extern char *passfile; extern char *passfile_default; -extern char *tempname; extern char *yppasswd_domain; extern int no_chsh; extern int no_chfn; @@ -80,3 +66,5 @@ extern int resvport; extern int inplace; extern int verbose; extern int _rpc_dtablesize(void); + +#endif diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c index 9b2ee5aafc..5c31905bb5 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c @@ -29,38 +29,41 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_main.c,v 1.14.2.2 2002/02/15 00:46:57 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_main.c,v 1.27 2008/10/30 01:54:31 rafan Exp $ * $DragonFly: src/usr.sbin/rpc.yppasswdd/yppasswdd_main.c,v 1.5 2005/11/25 00:32:49 swildner Exp $ */ -#include "yppasswd.h" -#include -#include -#include /* getenv, exit */ -#include -#include #include -#include /* for pmap_unset */ -#include /* strcmp */ -#include -#include #include #include -#ifdef __cplusplus -#include /* getdtablesize, open */ -#endif /* __cplusplus */ -#include #include +#include +#include #include -#include + #include #include +#include +#include +#include +#include +#include /* getenv, exit */ +#include +#include /* strcmp */ +#include +#include + +#include +#include +#include /* for pmap_unset */ #include -struct dom_binding {}; #include + +#include "yppasswd.h" #include "yppasswdd_extern.h" #include "yppasswd_private.h" #include "ypxfr_extern.h" +#include "yp_extern.h" #ifndef SIG_PF #define SIG_PF void(*)(int) @@ -80,10 +83,15 @@ static int _rpcfdtype; #define _SERVED 1 #define _SERVING 2 +static char _localhost[] = "localhost"; +static char _passwd_byname[] = "passwd.byname"; extern int _rpcsvcstate; /* Set when a request is serviced */ -char *progname = "rpc.yppasswdd"; -char *yp_dir = _PATH_YP; -char *passfile_default = _PATH_YP "master.passwd"; +static char _progname[] = "rpc.yppasswdd"; +char *progname = _progname; +static char _yp_dir[] = _PATH_YP; +char *yp_dir = _yp_dir; +static char _passfile_default[] = _PATH_YP "master.passwd"; +char *passfile_default = _passfile_default; char *passfile; char *yppasswd_domain = NULL; int no_chsh = 0; @@ -93,25 +101,25 @@ int multidomain = 0; int verbose = 0; int resvport = 1; int inplace = 0; -char *sockname = YP_SOCKNAME; +char sockname[] = YP_SOCKNAME; static void -terminate(int sig) +terminate(int sig __unused) { - svc_unregister(YPPASSWDPROG, YPPASSWDVERS); - svc_unregister(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); + rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); + rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); unlink(sockname); exit(0); } static void -reload(int sig) +reload(int sig __unused) { load_securenets(); } static void -closedown(int sig) +closedown(int sig __unused) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; @@ -140,7 +148,8 @@ closedown(int sig) alarm(_RPCSVC_CLOSEDOWN/2); } -static void usage(void) +static void +usage(void) { fprintf(stderr, "%s\n%s\n", "usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]", @@ -151,14 +160,18 @@ static void usage(void) int main(int argc, char *argv[]) { + struct rlimit rlim; SVCXPRT *transp = NULL; - int sock; - int proto = 0; struct sockaddr_in saddr; - int asize = sizeof (saddr); + socklen_t asize = sizeof (saddr); + struct netconfig *nconf; + struct sigaction sa; + void *localhandle; int ch; char *mastername; char myname[MAXHOSTNAMELEN + 2]; + int maxrec = RPC_MAXDATASIZE; + extern int debug; debug = 1; @@ -212,14 +225,14 @@ name isn't set -- aborting"); load_securenets(); - if (getrpcport("localhost", YPPROG, YPVERS, IPPROTO_UDP) <= 0) { + if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) { yp_error("no ypserv processes registered with local portmap"); yp_error("this host is not an NIS server -- aborting"); exit(1); } - if ((mastername = ypxfr_get_master(yppasswd_domain, "passwd.byname", - "localhost",0)) == NULL) { + if ((mastername = ypxfr_get_master(yppasswd_domain, + _passwd_byname, _localhost, 0)) == NULL) { yp_error("can't get name of NIS master server for domain %s", yppasswd_domain); exit(1); @@ -241,68 +254,65 @@ the %s domain -- aborting", yppasswd_domain); debug = 0; if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { - int ssize = sizeof (int); - + socklen_t ssize = sizeof (int); if (saddr.sin_family != AF_INET) exit(1); if (getsockopt(0, SOL_SOCKET, SO_TYPE, - (char *)&_rpcfdtype, &ssize) == -1) + (char *)&_rpcfdtype, &ssize) == -1) exit(1); - sock = 0; _rpcpmstart = 1; - proto = 0; - openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); - } else { - if (!debug) { - if (daemon(0,0)) { - err(1,"cannot fork"); - } - } - openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); - sock = RPC_ANYSOCK; - pmap_unset(YPPASSWDPROG, YPPASSWDVERS); - pmap_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS); - unlink(sockname); } - if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { - transp = svcudp_create(sock); - if (transp == NULL) { - yp_error("cannot create udp service."); - exit(1); - } - if (!_rpcpmstart) - proto = IPPROTO_UDP; - if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { - yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, udp)."); - exit(1); + if (!debug && _rpcpmstart == 0) { + if (daemon(0,0)) { + err(1,"cannot fork"); } } + openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_NOCLDWAIT; + sigaction(SIGCHLD, &sa, NULL); - if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { - transp = svctcp_create(sock, 0, 0); - if (transp == NULL) { - yp_error("cannot create tcp service."); - exit(1); - } - if (!_rpcpmstart) - proto = IPPROTO_TCP; - if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, proto)) { - yp_error("unable to register (YPPASSWDPROG, YPPASSWDVERS, tcp)."); - exit(1); - } + rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); + rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); + + rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); + + if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) { + yp_error("cannot create yppasswd service."); + exit(1); + } + if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG, + MASTER_YPPASSWDVERS, "netpath") == 0) { + yp_error("cannot create master_yppasswd service."); + exit(1); } + nconf = NULL; + localhandle = setnetconfig(); + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (nconf->nc_protofmly != NULL && + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } + if (nconf == NULL) { + yp_error("getnetconfigent unix: %s", nc_sperror()); + exit(1); + } unlink(sockname); - transp = svcunix_create(sock, 0, 0, sockname); + transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname); if (transp == NULL) { yp_error("cannot create AF_LOCAL service."); exit(1); } - if (!svc_register(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, master_yppasswdprog_1, 0)) { - yp_error("unable to register (MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, unix)."); + if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, + master_yppasswdprog_1, nconf)) { + yp_error("unable to register (MASTER_YPPASSWDPROG, \ + MASTER_YPPASSWDVERS, unix)."); exit(1); } + endnetconfig(localhandle); + /* Only root may connect() to the AF_UNIX link. */ if (chmod(sockname, 0)) err(1, "chmod of %s failed", sockname); @@ -315,14 +325,26 @@ the %s domain -- aborting", yppasswd_domain); signal(SIGALRM, (SIG_PF) closedown); alarm(_RPCSVC_CLOSEDOWN/2); } - /* set up resource limits and block signals */ - pw_init(); - /* except SIGCHLD, which we need to catch */ - install_reaper(1); - signal(SIGTERM, (SIG_PF) terminate); + /* Unlimited resource limits. */ + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + setrlimit(RLIMIT_CPU, &rlim); + setrlimit(RLIMIT_FSIZE, &rlim); + setrlimit(RLIMIT_STACK, &rlim); + setrlimit(RLIMIT_DATA, &rlim); + setrlimit(RLIMIT_RSS, &rlim); + + /* Don't drop core (not really necessary, but GP's). */ + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); + /* Turn off signals. */ + signal(SIGALRM, SIG_IGN); signal(SIGHUP, (SIG_PF) reload); + signal(SIGINT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, (SIG_PF) terminate); svc_run(); yp_error("svc_run returned"); diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_server.c b/usr.sbin/rpc.yppasswdd/yppasswdd_server.c index 279338cf9c..d08244e881 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_server.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_server.c @@ -29,70 +29,43 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_server.c,v 1.16.2.2 2002/02/15 00:46:57 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.yppasswdd/yppasswdd_server.c,v 1.29 2003/06/15 21:24:45 mbr Exp $ * $DragonFly: src/usr.sbin/rpc.yppasswdd/yppasswdd_server.c,v 1.7 2005/11/25 00:32:49 swildner Exp $ */ -#include -#include -#include -#include -#include -#include -#include +#include +#include #include -#include +#include +#include + #include -#include +#include + +#include #include -#include +#include #include +#include +#include #include +#include +#include +#include +#include + +#include +#include + #include #include -#include -#include -#include -#include -struct dom_binding {}; +struct dom_binding; #include #include "yppasswdd_extern.h" #include "yppasswd.h" #include "yppasswd_private.h" - -char *tempname; - -void -reaper(int sig) -{ - extern pid_t pid; - extern int pstat; - int st; - int saved_errno; - - saved_errno = errno; - - if (sig > 0) { - if (sig == SIGCHLD) - while (wait3(&st, WNOHANG, NULL) > 0) ; - } else { - pid = waitpid(pid, &pstat, 0); - } - - errno = saved_errno; - return; -} - -void -install_reaper(int on) -{ - if (on) { - signal(SIGCHLD, reaper); - } else { - signal(SIGCHLD, SIG_DFL); - } - return; -} +#include "ypxfr_extern.h" +#include "yp_extern.h" static struct passwd yp_password; @@ -104,7 +77,7 @@ copy_yp_pass(char *p, int x, int m) yp_password.pw_fields = 0; - buf = (char *)realloc(buf, m + 10); + buf = realloc(buf, m + 10); bzero(buf, m + 10); /* Turn all colons into NULLs */ @@ -148,7 +121,7 @@ copy_yp_pass(char *p, int x, int m) static int validchars(char *arg) { - int i; + size_t i; for (i = 0; i < strlen(arg); i++) { if (iscntrl(arg[i])) { @@ -169,7 +142,7 @@ validchars(char *arg) } static int -validate_master(struct passwd *opw, struct x_master_passwd *npw) +validate_master(struct passwd *opw __unused, struct x_master_passwd *npw) { if (npw->pw_name[0] == '+' || npw->pw_name[0] == '-') { @@ -203,7 +176,7 @@ validate(struct passwd *opw, struct x_passwd *npw) return(1); } - if (npw->pw_uid != opw->pw_uid) { + if ((uid_t)npw->pw_uid != opw->pw_uid) { yp_error("UID mismatch: client says user %s has UID %d", npw->pw_name, npw->pw_uid); yp_error("database says user %s has UID %d", opw->pw_name, @@ -211,7 +184,7 @@ validate(struct passwd *opw, struct x_passwd *npw) return(1); } - if (npw->pw_gid != opw->pw_gid) { + if ((gid_t)npw->pw_gid != opw->pw_gid) { yp_error("GID mismatch: client says user %s has GID %d", npw->pw_name, npw->pw_gid); yp_error("database says user %s has GID %d", opw->pw_name, @@ -274,7 +247,7 @@ find_domain(struct x_passwd *pw) } while ((dirp = readdir(dird)) != NULL) { - snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", + snprintf(yp_mapdir, sizeof yp_mapdir, "%s/%s", yp_dir, dirp->d_name); if (stat(yp_mapdir, &statbuf) < 0) { yp_error("stat(%s) failed: %s", yp_mapdir, @@ -291,10 +264,10 @@ find_domain(struct x_passwd *pw) &key, &data, 0) != YP_TRUE) { continue; } - *(char *)(data.data + data.size) = '\0'; + *((char *)data.data + data.size) = '\0'; copy_yp_pass(data.data, 1, data.size); - if (yp_password.pw_uid == pw->pw_uid && - yp_password.pw_gid == pw->pw_gid) { + if (yp_password.pw_uid == (uid_t)pw->pw_uid && + yp_password.pw_gid == (gid_t)pw->pw_gid) { hit++; snprintf(domain, YPMAXDOMAIN, "%s", tmp); } @@ -309,6 +282,20 @@ find_domain(struct x_passwd *pw) return((char *)&domain); } +static const char *maps[] = { + "master.passwd.byname", + "master.passwd.byuid", + "passwd.byname", + "passwd.byuid" +}; + +static const char *formats[] = { + "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s", + "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s", + "%s:%s:%d:%d:%s:%s:%s", + "%s:%s:%d:%d:%s:%s:%s" +}; + static int update_inplace(struct passwd *pw, char *domain) { @@ -318,23 +305,19 @@ update_inplace(struct passwd *pw, char *domain) char pwbuf[YPMAXRECORD]; char keybuf[20]; int i; - char *maps[] = { "master.passwd.byname", "master.passwd.byuid", - "passwd.byname", "passwd.byuid" }; - - char *formats[] = { "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s", - "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s", - "%s:%s:%d:%d:%s:%s:%s", "%s:%s:%d:%d:%s:%s:%s" }; char *ptr = NULL; - char *yp_last = "YP_LAST_MODIFIED"; + static char yp_last[] = "YP_LAST_MODIFIED"; char yplastbuf[YPMAXRECORD]; - snprintf(yplastbuf, sizeof(yplastbuf), "%lu", time(NULL)); + snprintf(yplastbuf, sizeof yplastbuf, "%llu", + (unsigned long long)time(NULL)); for (i = 0; i < 4; i++) { if (i % 2) { - snprintf(keybuf, sizeof(keybuf), "%ld", pw->pw_uid); - key.data = (char *)&keybuf; + snprintf(keybuf, sizeof keybuf, + "%llu", (unsigned long long)pw->pw_uid); + key.data = &keybuf; key.size = strlen(keybuf); } else { key.data = pw->pw_name; @@ -379,7 +362,8 @@ update_inplace(struct passwd *pw, char *domain) yp_error("warning: found entry for UID %d " "in map %s@%s with wrong name (%.*s)", pw->pw_uid, maps[i], domain, - ptr - (char *)data.data, data.data); + (int)(ptr - (char *)data.data), + (char *)data.data); yp_error("there may be more than one user " "with the same UID - continuing"); continue; @@ -389,7 +373,7 @@ update_inplace(struct passwd *pw, char *domain) * We're really being ultra-paranoid here. * This is generally a 'can't happen' condition. */ - snprintf(pwbuf, sizeof(pwbuf), ":%d:%d:", pw->pw_uid, + snprintf(pwbuf, sizeof pwbuf, ":%d:%d:", pw->pw_uid, pw->pw_gid); if (!strstr(data.data, pwbuf)) { yp_error("warning: found entry for user %s \ @@ -401,13 +385,13 @@ with the same name - continuing"); } if (i < 2) { - snprintf(pwbuf, sizeof(pwbuf), formats[i], + snprintf(pwbuf, sizeof pwbuf, formats[i], pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); } else { - snprintf(pwbuf, sizeof(pwbuf), formats[i], + snprintf(pwbuf, sizeof pwbuf, formats[i], pw->pw_name, *(ptr+1) == '*' ? "*" : pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell); @@ -449,21 +433,6 @@ with the same name - continuing"); return(0); } -static char * -yp_mktmpnam(void) -{ - static char path[MAXPATHLEN]; - char *p; - - sprintf(path,"%s",passfile); - if ((p = strrchr(path, '/'))) - ++p; - else - p = path; - strcpy(p, "yppwtmp.XXXXXX"); - return(mktemp(path)); -} - int * yppasswdproc_update_1_svc(yppasswd *argp, struct svc_req *rqstp) { @@ -480,6 +449,7 @@ yppasswdproc_update_1_svc(yppasswd *argp, struct svc_req *rqstp) char *oldgecos = NULL; char *passfile_hold; char passfile_buf[MAXPATHLEN + 2]; + char passfile_hold_buf[MAXPATHLEN + 2]; char *domain = yppasswd_domain; static struct sockaddr_in clntaddr; static struct timeval t_saved, t_test; @@ -494,17 +464,16 @@ yppasswdproc_update_1_svc(yppasswd *argp, struct svc_req *rqstp) rqhost = svc_getcaller(rqstp->rq_xprt); gettimeofday(&t_test, NULL); - if (!bcmp((char *)rqhost, (char *)&clntaddr, - sizeof(struct sockaddr_in)) && + if (!bcmp(rqhost, &clntaddr, sizeof *rqhost) && t_test.tv_sec > t_saved.tv_sec && t_test.tv_sec - t_saved.tv_sec < 300) { - bzero((char *)&clntaddr, sizeof(struct sockaddr_in)); - bzero((char *)&t_saved, sizeof(struct timeval)); + bzero(&clntaddr, sizeof clntaddr); + bzero(&t_saved, sizeof t_saved); return(NULL); } - bcopy((char *)rqhost, (char *)&clntaddr, sizeof(struct sockaddr_in)); + bcopy(rqhost, &clntaddr, sizeof clntaddr); gettimeofday(&t_saved, NULL); if (yp_access(resvport ? "master.passwd.byname" : NULL, rqstp)) { @@ -547,7 +516,7 @@ yppasswdproc_update_1_svc(yppasswd *argp, struct svc_req *rqstp) } /* Nul terminate, please. */ - *(char *)(data.data + data.size) = '\0'; + *((char *)data.data + data.size) = '\0'; copy_yp_pass(data.data, 1, data.size); @@ -605,33 +574,70 @@ yppasswdproc_update_1_svc(yppasswd *argp, struct svc_req *rqstp) passfile = (char *)&passfile_buf; } + /* + * Create a filename to hold the original master.passwd + * so if our call to yppwupdate fails we can roll back + */ + snprintf(passfile_hold_buf, sizeof(passfile_hold_buf), + "%s.hold", passfile); + passfile_hold = (char *)&passfile_hold_buf; + + /* Step 5: make a new password file with the updated info. */ - if ((pfd = pw_lock()) < 0) { - return (&result); + if (pw_init(dirname(passfile), passfile)) { + yp_error("pw_init() failed"); + return &result; } - if ((tfd = pw_tmp()) < 0) { - return (&result); + if ((pfd = pw_lock()) == -1) { + pw_fini(); + yp_error("pw_lock() failed"); + return &result; } - - if (pw_copy(pfd, tfd, &yp_password)) { - yp_error("failed to created updated password file -- \ -cleaning up and bailing out"); - unlink(tempname); - return(&result); + if ((tfd = pw_tmp(-1)) == -1) { + pw_fini(); + yp_error("pw_tmp() failed"); + return &result; + } + if (pw_copy(pfd, tfd, &yp_password, NULL) == -1) { + pw_fini(); + yp_error("pw_copy() failed"); + return &result; + } + if (rename(passfile, passfile_hold) == -1) { + pw_fini(); + yp_error("rename of %s to %s failed", passfile, + passfile_hold); + return &result; } - passfile_hold = yp_mktmpnam(); - rename(passfile, passfile_hold); - if (strcmp(passfile, _PATH_MASTERPASSWD)) { - rename(tempname, passfile); + if (strcmp(passfile, _PATH_MASTERPASSWD) == 0) { + /* + * NIS server is exporting the system's master.passwd. + * Call pw_mkdb to rebuild passwd and the .db files + */ + if (pw_mkdb(yp_password.pw_name) == -1) { + pw_fini(); + yp_error("pw_mkdb() failed"); + rename(passfile_hold, passfile); + return &result; + } } else { - if (pw_mkdb(argp->newpw.pw_name) < 0) { - yp_error("pwd_mkdb failed"); - return(&result); + /* + * NIS server is exporting a private master.passwd. + * Rename tempfile into final location + */ + if (rename(pw_tempname(), passfile) == -1) { + pw_fini(); + yp_error("rename of %s to %s failed", + pw_tempname(), passfile); + rename(passfile_hold, passfile); + return &result; } } + pw_fini(); + if (inplace) { if ((rval = update_inplace(&yp_password, domain))) { yp_error("inplace update failed -- rebuilding maps"); @@ -665,9 +671,8 @@ cleaning up and bailing out"); } if (verbose) { - yp_error("update completed for user %s (uid %d):", - argp->newpw.pw_name, - argp->newpw.pw_uid); + yp_error("update completed for user %s (uid %d) in %s:", + argp->newpw.pw_name, argp->newpw.pw_uid, passfile); if (passwd_changed) yp_error("password changed"); @@ -685,11 +690,6 @@ cleaning up and bailing out"); return (&result); } -struct cmessage { - struct cmsghdr cmsg; - struct cmsgcred cmcred; -}; - /* * Note that this function performs a little less sanity checking * than the last one. Since only the superuser is allowed to use it, @@ -701,47 +701,44 @@ yppasswdproc_update_master_1_svc(master_yppasswd *argp, struct svc_req *rqstp) static int result; int pfd, tfd; int pid; + uid_t uid; int rval = 0; DBT key, data; char *passfile_hold; char passfile_buf[MAXPATHLEN + 2]; + char passfile_hold_buf[MAXPATHLEN + 2]; struct sockaddr_in *rqhost; - struct cmessage *cm; - SVCXPRT *transp; + SVCXPRT *transp; result = 1; + transp = rqstp->rq_xprt; /* * NO AF_INET CONNETCIONS ALLOWED! */ - rqhost = svc_getcaller(rqstp->rq_xprt); + rqhost = svc_getcaller(transp); if (rqhost->sin_family != AF_UNIX) { yp_error("Alert! %s/%d attempted to use superuser-only \ procedure!\n", inet_ntoa(rqhost->sin_addr), rqhost->sin_port); - svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + svcerr_auth(transp, AUTH_BADCRED); return(&result); } - transp = rqstp->rq_xprt; - - if (transp->xp_verf.oa_length < sizeof(struct cmessage) || - transp->xp_verf.oa_base == NULL || - transp->xp_verf.oa_flavor != AUTH_UNIX) { + if (rqstp->rq_cred.oa_flavor != AUTH_SYS) { yp_error("caller didn't send proper credentials"); - svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + svcerr_auth(transp, AUTH_BADCRED); return(&result); } - cm = (struct cmessage *)transp->xp_verf.oa_base; - if (cm->cmsg.cmsg_type != SCM_CREDS) { + if (__rpc_get_local_uid(transp, &uid) < 0) { yp_error("caller didn't send proper credentials"); - svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); + svcerr_auth(transp, AUTH_BADCRED); return(&result); } - if (cm->cmcred.cmcred_euid) { + if (uid) { yp_error("caller euid is %d, expecting 0 -- rejecting request", - cm->cmcred.cmcred_euid); + uid); svcerr_auth(rqstp->rq_xprt, AUTH_BADCRED); return(&result); } @@ -776,7 +773,7 @@ allow additions to be made to the password database"); } else { /* Nul terminate, please. */ - *(char *)(data.data + data.size) = '\0'; + *((char *)data.data + data.size) = '\0'; copy_yp_pass(data.data, 1, data.size); } @@ -801,30 +798,64 @@ allow additions to be made to the password database"); passfile = (char *)&passfile_buf; } - if ((pfd = pw_lock()) < 0) { - return (&result); - } - if ((tfd = pw_tmp()) < 0) { - return (&result); - } - - if (pw_copy(pfd, tfd, (struct passwd *)&argp->newpw)) { - yp_error("failed to created updated password file -- \ -cleaning up and bailing out"); - unlink(tempname); - return(&result); - } - - passfile_hold = yp_mktmpnam(); - rename(passfile, passfile_hold); - if (strcmp(passfile, _PATH_MASTERPASSWD)) { - rename(tempname, passfile); + /* + * Create a filename to hold the original master.passwd + * so if our call to yppwupdate fails we can roll back + */ + snprintf(passfile_hold_buf, sizeof(passfile_hold_buf), + "%s.hold", passfile); + passfile_hold = (char *)&passfile_hold_buf; + + if (pw_init(dirname(passfile), passfile)) { + yp_error("pw_init() failed"); + return &result; + } + if ((pfd = pw_lock()) == -1) { + pw_fini(); + yp_error("pw_lock() failed"); + return &result; + } + if ((tfd = pw_tmp(-1)) == -1) { + pw_fini(); + yp_error("pw_tmp() failed"); + return &result; + } + if (pw_copy(pfd, tfd, (struct passwd *)&argp->newpw, NULL) == -1) { + pw_fini(); + yp_error("pw_copy() failed"); + return &result; + } + if (rename(passfile, passfile_hold) == -1) { + pw_fini(); + yp_error("rename of %s to %s failed", passfile, + passfile_hold); + return &result; + } + if (strcmp(passfile, _PATH_MASTERPASSWD) == 0) { + /* + * NIS server is exporting the system's master.passwd. + * Call pw_mkdb to rebuild passwd and the .db files + */ + if (pw_mkdb(argp->newpw.pw_name) == -1) { + pw_fini(); + yp_error("pw_mkdb() failed"); + rename(passfile_hold, passfile); + return &result; + } } else { - if (pw_mkdb(argp->newpw.pw_name) < 0) { - yp_error("pwd_mkdb failed"); - return(&result); + /* + * NIS server is exporting a private master.passwd. + * Rename tempfile into final location + */ + if (rename(pw_tempname(), passfile) == -1) { + pw_fini(); + yp_error("rename of %s to %s failed", + pw_tempname(), passfile); + rename(passfile_hold, passfile); + return &result; } } + pw_fini(); if (inplace) { if ((rval = update_inplace((struct passwd *)&argp->newpw, diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile index 7f1d33b71c..cbc9c8eff5 100644 --- a/usr.sbin/rpc.ypupdated/Makefile +++ b/usr.sbin/rpc.ypupdated/Makefile @@ -1,27 +1,23 @@ -# $FreeBSD: src/usr.sbin/rpc.ypupdated/Makefile,v 1.6 1999/08/28 01:19:43 peter Exp $ +# $FreeBSD: src/usr.sbin/rpc.ypupdated/Makefile,v 1.10 2004/12/21 08:47:34 ru Exp $ # $DragonFly: src/usr.sbin/rpc.ypupdated/Makefile,v 1.2 2003/06/17 04:30:02 dillon Exp $ +.PATH: ${.CURDIR}/../ypserv ${.CURDIR}/../../libexec/ypxfr + PROG= rpc.ypupdated +NOMAN= SRCS= ypupdate_prot_svc.c ypupdate_prot.h ypupdated_main.c \ yp_error.c update.c ypupdated_server.c \ yp_dblookup.c yp_dbwrite.c yp_dbdelete.c yp_dbupdate.c -.PATH: ${.CURDIR}/../ypserv ${.CURDIR}/../../libexec/ypxfr - -RPCDIR= ${DESTDIR}/usr/include/rpcsvc - -NOMAN= yes - -CFLAGS+= -I${.CURDIR}/../ypserv -I. -CFLAGS+= -I${.CURDIR}/../../libexec/ypxfr - #CFLAGS+= -DYP +CFLAGS+= -I${.CURDIR}/../ypserv -I. -I${.CURDIR}/../../libexec/ypxfr DPADD= ${LIBRPCSVC} LDADD= -lrpcsvc CLEANFILES= ypupdate_prot_svc.c ypupdate_prot.h +RPCDIR= ${DESTDIR}/usr/include/rpcsvc RPCGEN= rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that diff --git a/usr.sbin/rpc.ypupdated/update.c b/usr.sbin/rpc.ypupdated/update.c index 19d71ae467..8f9ad90fa7 100644 --- a/usr.sbin/rpc.ypupdated/update.c +++ b/usr.sbin/rpc.ypupdated/update.c @@ -28,7 +28,7 @@ * Mountain View, California 94043 * * @(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro - * $FreeBSD: src/usr.sbin/rpc.ypupdated/update.c,v 1.4.2.1 2002/02/15 00:46:57 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.ypupdated/update.c,v 1.8 2007/02/15 02:45:14 trhodes Exp $ * $DragonFly: src/usr.sbin/rpc.ypupdated/update.c,v 1.4 2005/11/25 00:32:49 swildner Exp $ */ @@ -81,6 +81,7 @@ static int _openchild(char *, FILE **, FILE **); * and update it if so. Returns the yp status, which is zero * if there is no access violation. */ +int mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, u_int datalen, char *data) { @@ -100,7 +101,7 @@ mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, printf("%s %s\n", key, data); #endif sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */ - UPDATEFILE, mapname); + UPDATEFILE, mapname); pid = _openchild(updater, &childargs, &childrslt); if (pid < 0) { return (YPERR_YPERR); @@ -127,19 +128,18 @@ mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, wait(&status); #ifdef WEXITSTATUS - if (WEXITSTATUS(status) != 0) { + if (WEXITSTATUS(status) != 0) #else - if (status.w_retcode != 0) { + if (status.w_retcode != 0) #endif return (YPERR_YPERR); - } return (yperrno); } /* * returns pid, or -1 for failure */ -static +static int _openchild(char *command, FILE **fto, FILE **ffrom) { int i; @@ -155,11 +155,7 @@ _openchild(char *command, FILE **fto, FILE **ffrom) if (pipe(pdfrom) < 0) { goto error2; } -#ifdef VFORK - switch (pid = vfork()) { -#else switch (pid = fork()) { -#endif case -1: goto error3; @@ -223,16 +219,6 @@ basename(char *path) #else /* YP */ -#ifdef foo -#define ERR_ACCESS 1 -#define ERR_MALLOC 2 -#define ERR_READ 3 -#define ERR_WRITE 4 -#define ERR_DBASE 5 -#define ERR_KEY 6 -extern char *malloc(); -#endif - static int match(char *, char *); /* @@ -240,15 +226,10 @@ static int match(char *, char *); * and update it if so. Returns the status, which is zero * if there is no access violation. This function updates * the local file and then shuts up. - * - * Parameters: - * name: Name of the requestor - * keylen: Not used - * datalen: Not used */ int -localupdate(char *name, char *filename, u_int op, u_int keylen, char *key, - u_int datalen, char *data) +localupdate(char *name, char *filename, u_int op, u_int keylen __unused, + char *key, u_int datalen __unused, char *data) { char line[256]; FILE *rf; @@ -343,4 +324,3 @@ match(char *line, char *name) (line[len] == ' ' || line[len] == '\t')); } #endif /* !YP */ - diff --git a/usr.sbin/rpc.ypupdated/yp_dbupdate.c b/usr.sbin/rpc.ypupdated/yp_dbupdate.c index 015e33742d..3e5d5824ff 100644 --- a/usr.sbin/rpc.ypupdated/yp_dbupdate.c +++ b/usr.sbin/rpc.ypupdated/yp_dbupdate.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.ypupdated/yp_dbupdate.c,v 1.3.2.1 2002/02/15 00:46:57 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.ypupdated/yp_dbupdate.c,v 1.9 2004/10/17 19:33:32 stefanf Exp $ * $DragonFly: src/usr.sbin/rpc.ypupdated/yp_dbupdate.c,v 1.5 2007/11/25 01:28:24 swildner Exp $ */ @@ -42,7 +42,6 @@ #include #include #include -struct dom_binding {}; #include #include #include "ypxfr_extern.h" diff --git a/usr.sbin/rpc.ypupdated/ypupdated_main.c b/usr.sbin/rpc.ypupdated/ypupdated_main.c index d36034e90e..510d42133a 100644 --- a/usr.sbin/rpc.ypupdated/ypupdated_main.c +++ b/usr.sbin/rpc.ypupdated/ypupdated_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/rpc.ypupdated/ypupdated_main.c,v 1.4.2.3 2002/02/15 00:46:58 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.ypupdated/ypupdated_main.c,v 1.10 2004/05/24 12:28:27 stefanf Exp $ * $DragonFly: src/usr.sbin/rpc.ypupdated/ypupdated_main.c,v 1.5 2005/11/25 00:32:49 swildner Exp $ */ @@ -37,6 +37,7 @@ #include #include /* getenv, exit */ #include /* for pmap_unset */ +#include #include /* strcmp */ #include #ifdef __cplusplus diff --git a/usr.sbin/rpc.ypupdated/ypupdated_server.c b/usr.sbin/rpc.ypupdated/ypupdated_server.c index 733ddbb3e8..19025412ab 100644 --- a/usr.sbin/rpc.ypupdated/ypupdated_server.c +++ b/usr.sbin/rpc.ypupdated/ypupdated_server.c @@ -35,13 +35,12 @@ * Center for Telecommunications Research * Columbia University, New York City * - * $FreeBSD: src/usr.sbin/rpc.ypupdated/ypupdated_server.c,v 1.3.2.1 2002/02/15 00:46:58 des Exp $ + * $FreeBSD: src/usr.sbin/rpc.ypupdated/ypupdated_server.c,v 1.7 2003/05/03 21:06:40 obrien Exp $ * $DragonFly: src/usr.sbin/rpc.ypupdated/ypupdated_server.c,v 1.3 2005/11/25 00:32:49 swildner Exp $ */ #include #include -#include #include #include #include diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile new file mode 100644 index 0000000000..2080f72da1 --- /dev/null +++ b/usr.sbin/rpcbind/Makefile @@ -0,0 +1,20 @@ +# $NetBSD: Makefile,v 1.3 2000/06/20 13:56:43 fvdl Exp $ +# $FreeBSD: src/usr.sbin/rpcbind/Makefile,v 1.7 2006/03/10 07:58:02 deischen Exp $ +# $DragonFly$ + + +PROG= rpcbind +MAN= 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 + +CFLAGS+= -DPORTMAP -DLIBWRAP + +.if !defined(NO_INET6) +CFLAGS+= -DINET6 +.endif + +DPADD= ${LIBWRAP} ${LIBUTIL} +LDADD= -lwrap -lutil + +.include diff --git a/usr.sbin/rpcbind/check_bound.c b/usr.sbin/rpcbind/check_bound.c new file mode 100644 index 0000000000..23851cf53b --- /dev/null +++ b/usr.sbin/rpcbind/check_bound.c @@ -0,0 +1,225 @@ +/* + * 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 + * + * @(#)check_bound.c 1.15 93/07/05 SMI; 1.11 89/04/21 Copyr 1989 Sun Micro + * $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/check_bound.c,v 1.5 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * check_bound.c + * Checks to see whether the program is still bound to the + * claimed address and returns the univeral merged address + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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->buf); + free(na); + return (TRUE); + } + + ans = bind(fd, (struct sockaddr *)na->buf, na->len); + + close(fd); + free(na->buf); + free(na); + + return (ans == 0 ? FALSE : TRUE); +} + +int +add_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused) +{ + struct fdlist *fdl; + struct netconfig *newnconf; + + newnconf = getnetconfigent(nconf->nc_netid); + if (newnconf == NULL) + return (-1); + fdl = malloc(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 0000000000..eb13e8d0e0 --- /dev/null +++ b/usr.sbin/rpcbind/pmap_svc.c @@ -0,0 +1,361 @@ +/* + * 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 + * + * @(#)pmap_svc.c 1.14 93/07/05 SMI; 1.23 89/04/05 Copyr 1984 Sun Micro + * $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/pmap_svc.c,v 1.5 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. + */ + +/* + * pmap_svc.c + * The server procedure for the version 2 portmaper. + * All the portmapper related interface from the portmap side. + */ + +#ifdef PORTMAP +#include +#include +#include +#include +#include +#include +#ifdef RPCBIND_DEBUG +#include +#endif +#include "rpcbind.h" + +static struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, rpcprot_t); +static bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long); +static bool_t pmapproc_getport(struct svc_req *, SVCXPRT *); +static bool_t pmapproc_dump(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) +{ + struct pmaplist *hit = NULL; + 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 __unused, SVCXPRT *xprt, unsigned long op) +{ + struct pmap reg; + RPCB rpcbreg; + long ans; + struct sockaddr_in *who; + uid_t uid; + 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 *)®)) { + svcerr_decode(xprt); + return (FALSE); + } + + if (!check_access(xprt, op, ®, PMAPVERS)) { + svcerr_weakauth(xprt); + return FALSE; + } + + who = svc_getcaller(xprt); + + /* + * Can't use getpwnam here. We might end up calling ourselves + * and looping. + */ + if (__rpc_get_local_uid(xprt, &uid) < 0) + rpcbreg.r_owner = "unknown"; + else if (uid == 0) + rpcbreg.r_owner = "superuser"; + else { + /* r_owner will be strdup-ed later */ + snprintf(uidbuf, sizeof uidbuf, "%d", uid); + rpcbreg.r_owner = uidbuf; + } + + rpcbreg.r_prog = reg.pm_prog; + rpcbreg.r_vers = reg.pm_vers; + + if (op == PMAPPROC_SET) { + char buf[32]; + + snprintf(buf, sizeof 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 __unused, 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 *)®)) { + svcerr_decode(xprt); + return (FALSE); + } + + if (!check_access(xprt, PMAPPROC_GETPORT, ®, 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; + snprintf(serveuaddr, sizeof 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) { + 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 __unused, 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) + 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 0000000000..51897e2669 --- /dev/null +++ b/usr.sbin/rpcbind/rpcb_stat.c @@ -0,0 +1,206 @@ +/* + * 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 + * + * @(#)rpcb_stat.c 1.7 94/04/25 SMI + * $NetBSD: rpcb_stat.c,v 1.2 2000/07/04 20:27:40 matt Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcb_stat.c,v 1.4 2003/10/29 09:29:23 mbr Exp $ + * $DragonFly$ + */ + +/* + * rpcb_stat.c + * Allows for gathering of statistics + * + * Copyright (c) 1990 by Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include +#endif +#include +#include +#include "rpcbind.h" + +static rpcb_stat_byvers inf; + +void +rpcbs_init(void) +{ + +} + +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] == 0)) + 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] == 0)) { + 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 __unused, struct svc_req *req __unused, + SVCXPRT *xprt __unused, rpcvers_t versnum __unused) +{ + return (void *)&inf; +} diff --git a/usr.sbin/rpcbind/rpcb_svc.c b/usr.sbin/rpcbind/rpcb_svc.c new file mode 100644 index 0000000000..53b21d17f3 --- /dev/null +++ b/usr.sbin/rpcbind/rpcb_svc.c @@ -0,0 +1,233 @@ +/* + * 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 + * + * @(#)rpcb_svc.c 1.16 93/07/05 SMI" + * $NetBSD: rpcb_svc.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc.c,v 1.3 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "rpcbind.h" + +static void *rpcbproc_getaddr_3_local(void *, struct svc_req *, SVCXPRT *, + rpcvers_t); +static void *rpcbproc_dump_3_local(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)(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); + svc_sendreply(transp, (xdrproc_t)xdr_void, 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; + } + memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, (xdrproc_t) xdr_argument, + (char *) &argument)) { + svcerr_decode(transp); + if (debugging) + 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) { + fprintf(stderr, "rpcbind: svc_sendreply\n"); + if (doabort) { + rpcbind_abort(); + } + } + } +done: + if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *) + &argument)) { + if (debugging) { + 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 __unused, + SVCXPRT *transp __unused, rpcvers_t versnum __unused) +{ + 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 __unused, struct svc_req *rqstp __unused, + SVCXPRT *transp __unused, rpcvers_t versnum __unused) +{ + 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 0000000000..82b66390d0 --- /dev/null +++ b/usr.sbin/rpcbind/rpcb_svc_4.c @@ -0,0 +1,454 @@ +/* + * 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 + * + * @(#)rpcb_svc_4.c 1.8 93/07/05 SMI + * $NetBSD: rpcb_svc_4.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc_4.c,v 1.5 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * rpcb_svc_4.c + * The server procedure for the version 4 rpcbind. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rpcbind.h" + +static void *rpcbproc_getaddr_4_local(void *, struct svc_req *, SVCXPRT *, + rpcvers_t); +static void *rpcbproc_getversaddr_4_local(void *, struct svc_req *, + SVCXPRT *, rpcvers_t); +static void *rpcbproc_getaddrlist_4_local(void *, struct svc_req *, + SVCXPRT *, rpcvers_t); +static void free_rpcb_entry_list(rpcb_entry_list_ptr *); +static void *rpcbproc_dump_4_local(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)(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); + svc_sendreply(transp, (xdrproc_t) xdr_void, 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) + 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) { + fprintf(stderr, "rpcbind: svc_sendreply\n"); + if (doabort) { + rpcbind_abort(); + } + } + } +done: + if (!svc_freeargs(transp, (xdrproc_t) xdr_argument, + (char *)&argument)) { + if (debugging) { + 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 __unused) +{ + 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 __unused) +{ + 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 __unused, + SVCXPRT *transp, rpcvers_t versnum __unused) +{ + RPCB *regp = (RPCB *)arg; + static rpcb_entry_list_ptr rlist; + 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); + tail = NULL; + 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\n", + 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 = malloc(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) +{ + 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 __unused, struct svc_req *req __unused, + SVCXPRT *xprt __unused, rpcvers_t versnum __unused) +{ + 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 0000000000..7c3d952325 --- /dev/null +++ b/usr.sbin/rpcbind/rpcb_svc_com.c @@ -0,0 +1,1468 @@ +/* + * 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 + * + * @(#)rpcb_svc_com.c 1.18 94/05/02 SMI + * $NetBSD: rpcb_svc_com.c,v 1.9 2002/11/08 00:16:39 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc_com.c,v 1.12 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * rpcb_svc_com.c + * The commom server procedure for the rpcbind. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include +#include +#endif /* PORTMAP */ +#include +#include + +#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(XDR *, struct encap_parms *); +static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *); +static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *); +static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *); +static int find_rmtcallfd_by_netid(char *); +static SVCXPRT *find_rmtcallxprt_by_fd(int); +static int forward_register(u_int32_t, struct netbuf *, int, + char *, rpcproc_t, rpcvers_t, + u_int32_t *); +static struct finfo *forward_find(u_int32_t); +static int free_slot_by_xid(u_int32_t); +static int free_slot_by_index(int); +static int netbufcmp(struct netbuf *, struct netbuf *); +static struct netbuf *netbufdup(struct netbuf *); +static void netbuffree(struct netbuf *); +static int check_rmtcalls(struct pollfd *, int); +static void xprt_set_caller(SVCXPRT *, struct finfo *); +static void send_svcsyserr(SVCXPRT *, struct finfo *); +static void handle_reply(int, SVCXPRT *); +static void find_versions(rpcprog_t, char *, rpcvers_t *, + rpcvers_t *); +static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *); +static char *getowner(SVCXPRT *, char *, size_t); +static int add_pmaplist(RPCB *); +static int del_pmaplist(RPCB *); + +/* + * Set a mapping of program, version, netid + */ +/* ARGSUSED */ +void * +rpcbproc_set_com(void *arg, struct svc_req *rqstp __unused, 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 = malloc(sizeof (RPCBLIST)); + if (rbl == 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(a->r_netid); + if (a->r_addr) + free(a->r_addr); + if (a->r_owner) + free(a->r_owner); + free(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 + add_pmaplist(regp); +#endif + return (TRUE); +} + +/* + * Unset a mapping of program, version, netid + */ +/* ARGSUSED */ +void * +rpcbproc_unset_com(void *arg, struct svc_req *rqstp __unused, 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(tmp->rpcb_map.r_addr); + free(tmp->rpcb_map.r_netid); + free(tmp->rpcb_map.r_owner); + free(tmp); + } +#ifdef PORTMAP + if (ans) + 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(unsigned int prog) +{ + RPCB reg; + 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); + map_unset(®, "superuser"); + free(reg.r_netid); + } +} + +void * +rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp __unused, + SVCXPRT *transp, rpcvers_t rpcbversnum, rpcvers_t verstype) +{ + static char *uaddr; + char *saddr = NULL; + rpcblist_ptr fnd; + + if (uaddr != NULL && uaddr != nullstring) { + free(uaddr); + uaddr = NULL; + } + 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 __unused, struct svc_req *rqstp __unused, + SVCXPRT *transp __unused, rpcvers_t rpcbversnum __unused) +{ + static time_t curtime; + + 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 __unused, + SVCXPRT *transp, rpcvers_t rpcbversnum __unused) +{ + char **uaddrp = (char **)arg; + struct netconfig *nconf; + static struct netbuf nbuf; + static struct netbuf *taddr; + + if (taddr) { + free(taddr->buf); + free(taddr); + taddr = NULL; + } + if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) || + ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) { + 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 __unused, + SVCXPRT *transp, rpcvers_t rpcbversnum __unused) +{ + 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 != NULL && uaddr != nullstring) { + free(uaddr); + uaddr = NULL; + } + 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 = malloc(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) +{ + 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 = NULL, *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(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 == NULL || uaddr[0] == '\0') { + svcerr_noprog(transp); + if (uaddr != NULL) + free(uaddr); + goto error; + } + free(uaddr); + } + nconf = rpcbind_get_conf(transp->xp_netid); + if (nconf == 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); + goto error; + } + xidp = __rpcb_get_dg_xidp(transp); + switch (forward_register(*xidp, caller, fd, m_uaddr, reply_type, + versnum, &call_msg.rm_xid)) { + case 1: + /* Success; forward_register() will free m_uaddr for us. */ + m_uaddr = NULL; + break; + case 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"); + goto error; + case -1: + /* forward_register failed. Perhaps no memory. */ + if (debugging) + fprintf(stderr, + "rpcbproc_callit_com: forward_register failed\n"); + 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) + free_slot_by_xid(call_msg.rm_xid); +out: + if (local_uaddr) + free(local_uaddr); + if (buf_alloc) + free(buf_alloc); + if (outbuf_alloc) + free(outbuf_alloc); + if (na) { + free(na->buf); + free(na); + } + if (m_uaddr != NULL) + free(m_uaddr); +} + +/* + * Makes an entry into the FIFO for the given request. + * Returns 1 on success, 0 if this is a duplicate request, or -1 on error. + * *callxidp is set to the xid of the call. + */ +static int +forward_register(u_int32_t caller_xid, struct netbuf *caller_addr, + int forward_fd, char *uaddr, rpcproc_t reply_type, + rpcvers_t versnum, u_int32_t *callxidp) +{ + 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(NULL); + /* initialization */ + if (lastxid == 0) + lastxid = time_now * NFORWARD; + + /* + * Check if it is a 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(NULL); + return (0); /* Duplicate entry */ + } else { + /* Should we wait any longer */ + if ((time_now - FINFO[i].time) > MAXTIME_OFF) + 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 { + 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; + /* Don't allow a zero xid below. */ + if ((u_int32_t)(lastxid + NFORWARD) <= NFORWARD) + lastxid = NFORWARD; + FINFO[j].forward_xid = lastxid + j; /* encode slot */ + *callxidp = FINFO[j].forward_xid; /* forward on this xid */ + return (1); +} + +static struct finfo * +forward_find(u_int32_t reply_xid) +{ + int i; + + i = reply_xid % (u_int32_t)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 % (u_int32_t)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(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; + + if ((np = malloc(sizeof(struct netbuf))) == NULL) + return (NULL); + if ((np->buf = malloc(ap->len)) == NULL) { + free(np); + return (NULL); + } + np->maxlen = np->len = ap->len; + memcpy(np->buf, ap->buf, ap->len); + return (np); +} + +static void +netbuffree(struct netbuf *ap) +{ + free(ap->buf); + free(ap); +} + + +#define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) +extern bool_t __svc_clean_idle(fd_set *, int, bool_t); + +void +my_svc_run(void) +{ + size_t nfds; + struct pollfd pollfds[FD_SETSIZE]; + int poll_ret, check_ret; + int n; +#ifdef SVC_RUN_DEBUG + int i; +#endif + struct pollfd *p; + fd_set cleanfds; + + 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, 30 * 1000)) { + 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: + cleanfds = svc_fdset; + __svc_clean_idle(&cleanfds, 30, FALSE); + 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) + 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) + 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(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 + free_slot_by_xid(reply_msg.rm_xid); + return; +} + +static void +find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp) +{ + rpcblist_ptr rbl; + unsigned int lowv = 0; + unsigned 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) +{ + rpcblist_ptr hit = NULL; + 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) +{ + uid_t uid; + + if (__rpc_get_local_uid(transp, &uid) < 0) + strlcpy(owner, "unknown", ownersize); + else if (uid == 0) + strlcpy(owner, "superuser", ownersize); + else + snprintf(owner, ownersize, "%d", 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 an 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 = malloc(sizeof (struct pmaplist)); + if (pml == NULL) { + 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; + unsigned 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] == 0) { + prot = 0; /* Remove all occurrences */ + } else { + /* Not an 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(fnd); + } + return (0); +} +#endif /* PORTMAP */ diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8 new file mode 100644 index 0000000000..18d459a271 --- /dev/null +++ b/usr.sbin/rpcbind/rpcbind.8 @@ -0,0 +1,149 @@ +.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4 +.\" Copyright 1989 AT&T +.\" Copyright 1991 Sun Microsystems, Inc. +.\" $FreeBSD: src/usr.sbin/rpcbind/rpcbind.8,v 1.10 2007/04/23 07:09:25 matteo Exp $ +.\" $DragonFly$ +.Dd April 23, 2007 +.Dt RPCBIND 8 +.Os +.Sh NAME +.Nm rpcbind +.Nd universal addresses to RPC program number mapper +.Sh SYNOPSIS +.Nm +.Op Fl 6adiLls +.Op Fl h Ar bindip +.Sh DESCRIPTION +The +.Nm +utility 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 +The +.Nm +utility 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 +The +.Nm +utility can only be started by the super-user. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl 6 +Bind to AF_INET6 (IPv6) addresses only. +.It Fl a +When debugging +.Pq Fl d , +do an abort on errors. +.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 if +.Fl a +is also specified. +With this option, the name-to-address translation consistency +checks are shown in detail. +.It Fl h Ar bindip +Specify specific IP addresses to bind to for TCP and UDP requests. +This option +may be specified multiple times and is typically necessary when running +on a multi-homed host. +If no +.Fl h +option is specified, +.Nm +will bind to +.Dv INADDR_ANY , +which could lead to problems on a multi-homed host due to +.Nm +returning a UDP packet from a different IP address than it was +sent to. +Note that when specifying IP addresses with +.Fl h , +.Nm +will automatically add +.Li 127.0.0.1 +and if IPv6 is enabled, +.Li ::1 +to the list. +.It Fl i +.Dq Insecure +mode. +Allow 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 +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 . +.It Fl l +Turn on libwrap connection logging. +.It Fl s +Cause +.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. +.El +.Sh NOTES +All RPC servers must be restarted if +.Nm +is restarted. +.Sh FILES +.Bl -tag -width /var/run/rpcbind.sock -compact +.It Pa /var/run/rpcbind.sock +.El +.Sh SEE ALSO +.Xr rpcbind 3 , +.Xr netconfig 5 , +.Xr rpcinfo 8 diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c new file mode 100644 index 0000000000..82fe29a7dd --- /dev/null +++ b/usr.sbin/rpcbind/rpcbind.c @@ -0,0 +1,773 @@ +/* + * 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 + * + * @(#)rpcbind.c 1.19 94/04/25 SMI; 1.35 89/04/21 Copyr 1984 Sun Micro + * $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcbind.c,v 1.20 2008/02/14 20:12:23 yar Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. + */ + +/* + * rpcbind.c + * Implements the program, version to address mapping for rpc. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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" + +#define RPCBINDDLOCK "/var/run/rpcbind.lock" + +int runasdaemon = 0; +int insecure = 0; +int oldstyle_local = 0; +int verboselog = 0; + +char **hosts = NULL; +int ipv6_only = 0; +int nhosts = 0; +int on = 1; +int rpcbindlockfd; + +#ifdef WARMSTART +/* Local Variable */ +static int warmstart = 0; /* Grab an 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"; + +static int init_transport(struct netconfig *); +static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *, + struct netbuf *); +static void terminate(int); +static void parseargs(int, char *[]); + +int +main(int argc, char *argv[]) +{ + struct netconfig *nconf; + void *nc_handle; /* Net config handle */ + struct rlimit rl; + int maxrec = RPC_MAXDATASIZE; + + parseargs(argc, argv); + + /* Check that another rpcbind isn't already running. */ + if ((rpcbindlockfd = (open(RPCBINDDLOCK, + O_RDONLY|O_CREAT, 0444))) == -1) + err(1, "%s", RPCBINDDLOCK); + + if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) + errx(1, "another rpcbind is already running. Aborting"); + + 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("local"); + if (nconf == NULL) + nconf = getnetconfigent("unix"); + if (nconf == NULL) { + syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); + exit(1); + } + + rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); + + init_transport(nconf); + + while ((nconf = getnetconfig(nc_handle))) { + if (nconf->nc_flag & NC_VISIBLE) + if (ipv6_only == 1 && strcmp(nconf->nc_protofmly, + "inet") == 0) { + /* DO NOTHING */ + } else + init_transport(nconf); + } + endnetconfig(nc_handle); + + /* catch the usual termination signals for graceful exit */ + signal(SIGCHLD, reap); + signal(SIGINT, terminate); + signal(SIGTERM, terminate); + signal(SIGQUIT, terminate); + /* ignore others that could get sent */ + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + 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; + int nhostsbak; + int bound; + struct sockaddr *sa; + u_int32_t host_addr[4]; /* IPv4 or IPv6 */ + 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; + + 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 ((strcmp(nconf->nc_netid, "local") == 0) || + (strcmp(nconf->nc_netid, "unix") == 0)) { + /* + * For other transports we call this later, for each socket we + * like to bind. + */ + if ((fd = __rpc_nconf2fd(nconf)) < 0) { + int non_fatal = 0; + if (errno == EPROTONOSUPPORT) + non_fatal = 1; + syslog(non_fatal?LOG_DEBUG: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, "local") == 0) || + (strcmp(nconf->nc_netid, "unix") == 0)) { + 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 ((strcmp(nconf->nc_netid, "local") != 0) && + (strcmp(nconf->nc_netid, "unix") != 0)) { + /* + * If no hosts were specified, just bind to INADDR_ANY. + * Otherwise make sure 127.0.0.1 is added to the list. + */ + nhostsbak = nhosts; + nhostsbak++; + hosts = realloc(hosts, nhostsbak * sizeof(char *)); + if (nhostsbak == 1) + hosts[0] = "*"; + else { + if (hints.ai_family == AF_INET) { + hosts[nhostsbak - 1] = "127.0.0.1"; + } else if (hints.ai_family == AF_INET6) { + hosts[nhostsbak - 1] = "::1"; + } else + return 1; + } + + /* + * Bind to specific IPs if asked to + */ + bound = 0; + while (nhostsbak > 0) { + --nhostsbak; + /* + * XXX - using RPC library internal functions. + */ + if ((fd = __rpc_nconf2fd(nconf)) < 0) { + int non_fatal = 0; + if (errno == EPROTONOSUPPORT && + nconf->nc_semantics != NC_TPI_CLTS) + non_fatal = 1; + syslog(non_fatal ? LOG_DEBUG : LOG_ERR, + "cannot create socket for %s", nconf->nc_netid); + return (1); + } + switch (hints.ai_family) { + case AF_INET: + if (inet_pton(AF_INET, hosts[nhostsbak], + host_addr) == 1) { + hints.ai_flags &= AI_NUMERICHOST; + } else { + /* + * Skip if we have an AF_INET6 address. + */ + if (inet_pton(AF_INET6, + hosts[nhostsbak], host_addr) == 1) { + close(fd); + continue; + } + } + break; + case AF_INET6: + if (inet_pton(AF_INET6, hosts[nhostsbak], + host_addr) == 1) { + hints.ai_flags &= AI_NUMERICHOST; + } else { + /* + * Skip if we have an AF_INET address. + */ + if (inet_pton(AF_INET, hosts[nhostsbak], + host_addr) == 1) { + close(fd); + continue; + } + } + if (setsockopt(fd, IPPROTO_IPV6, + IPV6_V6ONLY, &on, sizeof on) < 0) { + syslog(LOG_ERR, + "can't set v6-only binding for " + "ipv6 socket: %m"); + continue; + } + break; + default: + break; + } + + /* + * If no hosts were specified, just bind to INADDR_ANY + */ + if (strcmp("*", hosts[nhostsbak]) == 0) + hosts[nhostsbak] = NULL; + if ((strcmp(nconf->nc_netid, "local") != 0) && + (strcmp(nconf->nc_netid, "unix") != 0)) { + if ((aicode = getaddrinfo(hosts[nhostsbak], + servname, &hints, &res)) != 0) { + syslog(LOG_ERR, + "cannot get local address for %s: %s", + nconf->nc_netid, gai_strerror(aicode)); + continue; + } + 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 on %s: %m", + (hosts[nhostsbak] == NULL) ? "*" : + hosts[nhostsbak], nconf->nc_netid); + if (res != NULL) + freeaddrinfo(res); + continue; + } else + bound = 1; + 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); + fprintf(stderr, "rpcbind : my address is %s\n", uaddr); + free(uaddr); + } +#endif + + if (nconf->nc_semantics != NC_TPI_CLTS) + listen(fd, SOMAXCONN); + + my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); + if (my_xprt == (SVCXPRT *)NULL) { + syslog(LOG_ERR, "%s: could not create service", + nconf->nc_netid); + goto error; + } + } + if (!bound) + return 1; + } else { + 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; + } + 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); + fprintf(stderr, "rpcbind : my address is %s\n", uaddr); + free(uaddr); + } +#endif + + if (nconf->nc_semantics != NC_TPI_CLTS) + listen(fd, SOMAXCONN); + + my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); + 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) || + (strcmp(nconf->nc_netid, "local") == 0)) { + struct pmaplist *pml; + + if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, + pmap_service, 0)) { + syslog(LOG_ERR, "could not register on %s", + nconf->nc_netid); + goto error; + } + pml = malloc(sizeof (struct pmaplist)); + if (pml == 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, "local") == 0) + pml->pml_map.pm_prot = IPPROTO_ST; + 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 = malloc(sizeof (struct pmaplist)); + if (pml == 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 = malloc (sizeof (struct pmaplist)); + if (pml == 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 = malloc(sizeof (rpcblist)); + if (rbl == 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 __unused) +{ + close(rpcbindlockfd); +#ifdef WARMSTART + syslog(LOG_ERR, + "rpcbind terminating on signal. Restart with \"rpcbind -w\""); + write_warmstart(); /* Dump yourself */ +#endif + exit(2); +} + +void +rpcbind_abort(void) +{ +#ifdef WARMSTART + write_warmstart(); /* Dump yourself */ +#endif + abort(); +} + +/* get command line options */ +static void +parseargs(int argc, char *argv[]) +{ + int c; + +#ifdef WARMSTART +#define WSOP "w" +#else +#define WSOP "" +#endif + while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) { + switch (c) { + case '6': + ipv6_only = 1; + break; + case 'a': + doabort = 1; /* when debugging, do an abort on */ + break; /* errors; for rpcbind developers */ + /* only! */ + case 'd': + debugging = 1; + break; + case 'h': + ++nhosts; + hosts = realloc(hosts, nhosts * sizeof(char *)); + if (hosts == NULL) + errx(1, "Out of memory"); + hosts[nhosts - 1] = strdup(optarg); + if (hosts[nhosts - 1] == NULL) + errx(1, "Out of memory"); + 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 [-6adiLls%s] [-h bindip]\n", + WSOP); + exit (1); + } + } + if (doabort && !debugging) { + fprintf(stderr, + "-a (abort) specified without -d (debugging) -- ignored.\n"); + doabort = 0; + } +#undef WSOP +} + +void +reap(int dummy __unused) +{ + int save_errno = errno; + + while (wait3(NULL, WNOHANG, NULL) > 0) + ; + errno = save_errno; +} + +void +toggle_verboselog(int dummy __unused) +{ + verboselog = !verboselog; +} diff --git a/usr.sbin/rpcbind/rpcbind.h b/usr.sbin/rpcbind/rpcbind.h new file mode 100644 index 0000000000..14ad55b6b2 --- /dev/null +++ b/usr.sbin/rpcbind/rpcbind.h @@ -0,0 +1,142 @@ +/* + * 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 + * + * @(#)rpcbind.h 1.4 90/04/12 SMI + * $NetBSD: rpcbind.h,v 1.1 2000/06/03 00:47:21 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/rpcbind.h,v 1.3 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * rpcbind.h + * The common header declarations + */ + +#ifndef _RPCBIND_H_ +#define _RPCBIND_H_ + +#ifdef PORTMAP +#include +#endif +#include + +/* + * 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(struct netconfig *, struct netbuf *); +bool_t is_bound(char *, char *); +char *mergeaddr(SVCXPRT *, char *, char *, char *); +struct netconfig *rpcbind_get_conf(char *); + +void rpcbs_init(void); +void rpcbs_procinfo(rpcvers_t, rpcproc_t); +void rpcbs_set(rpcvers_t, bool_t); +void rpcbs_unset(rpcvers_t, bool_t); +void rpcbs_getaddr(rpcvers_t, rpcprog_t, rpcvers_t, char *, char *); +void rpcbs_rmtcall(rpcvers_t, rpcproc_t, rpcprog_t, rpcvers_t, rpcproc_t, + char *, rpcblist_ptr); +void *rpcbproc_getstat(void *, struct svc_req *, SVCXPRT *, rpcvers_t); + +void rpcb_service_3(struct svc_req *, SVCXPRT *); +void rpcb_service_4(struct svc_req *, SVCXPRT *); + +/* Common functions shared between versions */ +void *rpcbproc_set_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t); +void *rpcbproc_unset_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t); +bool_t map_set(RPCB *, char *); +bool_t map_unset(RPCB *, char *); +void delete_prog(unsigned int); +void *rpcbproc_getaddr_com(RPCB *, struct svc_req *, SVCXPRT *, rpcvers_t, + rpcvers_t); +void *rpcbproc_gettime_com(void *, struct svc_req *, SVCXPRT *, + rpcvers_t); +void *rpcbproc_uaddr2taddr_com(void *, struct svc_req *, + SVCXPRT *, rpcvers_t); +void *rpcbproc_taddr2uaddr_com(void *, struct svc_req *, SVCXPRT *, + rpcvers_t); +int create_rmtcall_fd(struct netconfig *); +void rpcbproc_callit_com(struct svc_req *, SVCXPRT *, rpcvers_t, + rpcvers_t); +void my_svc_run(void); + +void rpcbind_abort(void); +void reap(int); +void toggle_verboselog(int); + +int check_access(SVCXPRT *, rpcproc_t, void *, unsigned int); +int check_callit(SVCXPRT *, struct r_rmtcall_args *, int); +void logit(int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *); +int is_loopback(struct netbuf *); + +#ifdef PORTMAP +extern void pmap_service(struct svc_req *, SVCXPRT *); +#endif + +void write_warmstart(void); +void read_warmstart(void); + +char *addrmerge(struct netbuf *, char *, char *, char *); +void network_init(void); +struct sockaddr *local_sa(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 0000000000..07ec53c020 --- /dev/null +++ b/usr.sbin/rpcbind/security.c @@ -0,0 +1,289 @@ +/* $NetBSD: security.c,v 1.5 2000/06/08 09:01:05 fvdl Exp $ */ +/* $FreeBSD: src/usr.sbin/rpcbind/security.c,v 1.6 2002/12/16 22:24:26 mbr Exp $ */ +/* $DragonFly$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * XXX for special case checks in check_callit. + */ +#include +#include +#include +#include +#include +#include + +#include "rpcbind.h" + +#ifdef LIBWRAP +# include +#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, unsigned 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: + break; + } + +#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: + break; + } + + 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, "local"); + 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 __unused) +{ + 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: + break; + } + default: + break; + } + + 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 0000000000..8fe42fe5e6 --- /dev/null +++ b/usr.sbin/rpcbind/util.c @@ -0,0 +1,382 @@ +/*- + * 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. + * + * $NetBSD: util.c,v 1.4 2000/08/03 00:04:30 fvdl Exp $ + * $FreeBSD: src/usr.sbin/rpcbind/util.c,v 1.6 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rpcbind.h" + +#define SA2SIN(sa) ((struct sockaddr_in *)(sa)) +#define SA2SINADDR(sa) (SA2SIN(sa)->sin_addr) +#ifdef INET6 +#define SA2SIN6(sa) ((struct sockaddr_in6 *)(sa)) +#define SA2SIN6ADDR(sa) (SA2SIN6(sa)->sin6_addr) +#endif + +static struct sockaddr_in *local_in4; +#ifdef INET6 +static struct sockaddr_in6 *local_in6; +#endif + +static int bitmaskcmp(void *, void *, void *, int); +#ifdef INET6 +static void in6_fillscopeid(struct sockaddr_in6 *); +#endif + +/* + * For all bits set in "mask", compare the corresponding bits in + * "dst" and "src", and see if they match. Returns 0 if the addresses + * match. + */ +static int +bitmaskcmp(void *dst, void *src, void *mask, int bytelen) +{ + int i; + u_int8_t *p1 = dst, *p2 = src, *netmask = mask; + + for (i = 0; i < bytelen; i++) + if ((p1[i] & netmask[i]) != (p2[i] & netmask[i])) + return (1); + return (0); +} + +/* + * Similar to code in ifconfig.c. Fill in the scope ID for link-local + * addresses returned by getifaddrs(). + */ +#ifdef INET6 +static void +in6_fillscopeid(struct sockaddr_in6 *sin6) +{ + u_int16_t ifindex; + + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + ifindex = ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); + if (sin6->sin6_scope_id == 0 && ifindex != 0) { + sin6->sin6_scope_id = ifindex; + *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 0; + } + } +} +#endif + +/* + * Find a server address that can be used by `caller' to contact + * the local service specified by `serv_uaddr'. If `clnt_uaddr' is + * non-NULL, it is used instead of `caller' as a hint suggesting + * the best address (e.g. the `r_addr' field of an rpc, which + * contains the rpcbind server address that the caller used). + * + * Returns the best server address as a malloc'd "universal address" + * string which should be freed by the caller. On error, returns NULL. + */ +char * +addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr, + char *netid) +{ + struct ifaddrs *ifap, *ifp = NULL, *bestif; + struct netbuf *serv_nbp = NULL, *hint_nbp = NULL, tbuf; + struct sockaddr *caller_sa, *hint_sa, *ifsa, *ifmasksa, *serv_sa; + struct sockaddr_storage ss; + struct netconfig *nconf; + char *caller_uaddr = NULL, *hint_uaddr = NULL; + char *ret = NULL; + +#ifdef ND_DEBUG + if (debugging) + fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr, + clnt_uaddr == NULL ? "NULL" : clnt_uaddr, netid); +#endif + caller_sa = caller->buf; + if ((nconf = rpcbind_get_conf(netid)) == NULL) + goto freeit; + if ((caller_uaddr = taddr2uaddr(nconf, caller)) == NULL) + goto freeit; + + /* + * Use `clnt_uaddr' as the hint if non-NULL, but ignore it if its + * address family is different from that of the caller. + */ + hint_sa = NULL; + if (clnt_uaddr != NULL) { + hint_uaddr = clnt_uaddr; + if ((hint_nbp = uaddr2taddr(nconf, clnt_uaddr)) == NULL) + goto freeit; + hint_sa = hint_nbp->buf; + } + if (hint_sa == NULL || hint_sa->sa_family != caller_sa->sa_family) { + hint_uaddr = caller_uaddr; + hint_sa = caller->buf; + } + +#ifdef ND_DEBUG + if (debugging) + fprintf(stderr, "addrmerge: hint %s\n", hint_uaddr); +#endif + /* Local caller, just return the server address. */ + if (strncmp(caller_uaddr, "0.0.0.0.", 8) == 0 || + strncmp(caller_uaddr, "::.", 3) == 0 || caller_uaddr[0] == '/') { + ret = strdup(serv_uaddr); + goto freeit; + } + + if (getifaddrs(&ifp) < 0) + goto freeit; + + /* + * 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. + */ + bestif = NULL; + for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { + ifsa = ifap->ifa_addr; + ifmasksa = ifap->ifa_netmask; + + if (ifsa == NULL || ifsa->sa_family != hint_sa->sa_family || + !(ifap->ifa_flags & IFF_UP)) + continue; + + switch (hint_sa->sa_family) { + case AF_INET: + /* + * If the hint address matches this interface + * address/netmask, then we're done. + */ + if (!bitmaskcmp(&SA2SINADDR(ifsa), + &SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa), + sizeof(struct in_addr))) { + bestif = ifap; + goto found; + } + break; +#ifdef INET6 + case AF_INET6: + /* + * For v6 link local addresses, if the caller is on + * a link-local address then use the scope id to see + * which one. + */ + in6_fillscopeid(SA2SIN6(ifsa)); + if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa)) && + IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) && + IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa))) { + if (SA2SIN6(ifsa)->sin6_scope_id == + SA2SIN6(caller_sa)->sin6_scope_id) { + bestif = ifap; + goto found; + } + } else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa), + &SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa), + sizeof(struct in6_addr))) { + bestif = ifap; + goto found; + } + break; +#endif + default: + continue; + } + + /* + * Remember the first possibly useful interface, preferring + * "normal" to point-to-point and loopback ones. + */ + if (bestif == NULL || + (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) && + (bestif->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))) + bestif = ifap; + } + if (bestif == NULL) + goto freeit; + +found: + /* + * Construct the new address using the the address from + * `bestif', and the port number from `serv_uaddr'. + */ + serv_nbp = uaddr2taddr(nconf, serv_uaddr); + if (serv_nbp == NULL) + goto freeit; + serv_sa = serv_nbp->buf; + + memcpy(&ss, bestif->ifa_addr, bestif->ifa_addr->sa_len); + switch (ss.ss_family) { + case AF_INET: + SA2SIN(&ss)->sin_port = SA2SIN(serv_sa)->sin_port; + break; +#ifdef INET6 + case AF_INET6: + SA2SIN6(&ss)->sin6_port = SA2SIN6(serv_sa)->sin6_port; + break; +#endif + } + tbuf.len = ss.ss_len; + tbuf.maxlen = sizeof(ss); + tbuf.buf = &ss; + ret = taddr2uaddr(nconf, &tbuf); + +freeit: + if (caller_uaddr != NULL) + free(caller_uaddr); + if (hint_nbp != NULL) { + free(hint_nbp->buf); + free(hint_nbp); + } + if (serv_nbp != NULL) { + free(serv_nbp->buf); + free(serv_nbp); + } + if (ifp != NULL) + freeifaddrs(ifp); + +#ifdef ND_DEBUG + if (debugging) + fprintf(stderr, "addrmerge: returning %s\n", ret); +#endif + return ret; +} + +void +network_init(void) +{ +#ifdef INET6 + struct ifaddrs *ifap, *ifp; + struct ipv6_mreq mreq6; + unsigned int ifindex; + int 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 IPv6 multicast-capable + * interface, join the RPC multicast group on that interface. + */ + 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 0000000000..fd8ac9c2f1 --- /dev/null +++ b/usr.sbin/rpcbind/warmstart.c @@ -0,0 +1,180 @@ +/* + * 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 an earlier dumped file. + * + * Copyright (c) 1990 by Sun Microsystems, Inc. + */ + +/* + * @(#)warmstart.c 1.7 93/07/05 SMI + * $FreeBSD: src/usr.sbin/rpcbind/warmstart.c,v 1.4 2007/11/07 10:53:39 kevlo Exp $ + * $DragonFly$ + */ +#include +#include +#include +#include +#include +#include +#ifdef PORTMAP +#include +#include +#endif +#include +#include + +#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(char *, xdrproc_t, void *); +static bool_t read_struct(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); + } + } + 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, (xdrproc_t)xdr_rpcblist_ptr, &list_rbl); +#ifdef PORTMAP + write_struct(PMAPFILE, (xdrproc_t)xdr_pmaplist_ptr, &list_pml); +#endif + +} + +void +read_warmstart(void) +{ + rpcblist_ptr tmp_rpcbl = NULL; +#ifdef PORTMAP + struct pmaplist *tmp_pmapl = NULL; +#endif + int ok1, ok2 = TRUE; + + ok1 = read_struct(RPCBFILE, (xdrproc_t)xdr_rpcblist_ptr, &tmp_rpcbl); + if (ok1 == FALSE) + return; +#ifdef PORTMAP + ok2 = read_struct(PMAPFILE, (xdrproc_t)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/spray/spray.c b/usr.sbin/spray/spray.c index d71a842a97..a2db1c0607 100644 --- a/usr.sbin/spray/spray.c +++ b/usr.sbin/spray/spray.c @@ -137,7 +137,8 @@ main(int argc, char *argv[]) /* Clear server statistics */ - if (clnt_call(cl, SPRAYPROC_CLEAR, xdr_void, NULL, xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(cl, SPRAYPROC_CLEAR, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { clnt_perror(cl, getprogname()); exit(1); } @@ -148,7 +149,8 @@ main(int argc, char *argv[]) fflush (stdout); for (i = 0; i < count; i++) { - clnt_call(cl, SPRAYPROC_SPRAY, (xdrproc_t)xdr_sprayarr, &host_array, xdr_void, NULL, ONE_WAY); + clnt_call(cl, SPRAYPROC_SPRAY, (xdrproc_t)xdr_sprayarr, + &host_array, (xdrproc_t)xdr_void, NULL, ONE_WAY); if (delay) { usleep(delay); @@ -157,7 +159,8 @@ main(int argc, char *argv[]) /* Collect statistics from server */ - if (clnt_call(cl, SPRAYPROC_GET, xdr_void, NULL, (xdrproc_t)xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(cl, SPRAYPROC_GET, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) { clnt_perror(cl, getprogname()); exit(1); } diff --git a/usr.sbin/ypbind/yp_ping.c b/usr.sbin/ypbind/yp_ping.c index cebbd3dc83..423f7c97bc 100644 --- a/usr.sbin/ypbind/yp_ping.c +++ b/usr.sbin/ypbind/yp_ping.c @@ -31,17 +31,10 @@ * * @(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro * @(#)from: clnt_udp.c 2.2 88/08/01 4.0 RPCSRC - * $FreeBSD: src/usr.sbin/ypbind/yp_ping.c,v 1.6.2.1 2002/02/15 00:46:59 des Exp $ + * $FreeBSD: src/usr.sbin/ypbind/yp_ping.c,v 1.17 2008/09/15 14:01:40 dfr Exp $ * $DragonFly: src/usr.sbin/ypbind/yp_ping.c,v 1.7 2005/11/24 22:23:02 swildner Exp $ */ -/* - * What follows is a special version of clntudp_call() that has been - * hacked to send requests and receive replies asynchronously. Similar - * magic is used inside rpc.nisd(8) for the special non-blocking, - * non-fork()ing, non-threading callback support. - */ - /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -83,242 +76,20 @@ #include #include #include +#include #include #include #include #include +#include +#include #include +#include #include +#include #include -#include "yp_ping.h" - -#ifndef timeradd -#ifndef _KERNEL /* use timevaladd/timevalsub in kernel */ -/* NetBSD/OpenBSD compatible interfaces */ -#define timeradd(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ - if ((vvp)->tv_usec >= 1000000) { \ - (vvp)->tv_sec++; \ - (vvp)->tv_usec -= 1000000; \ - } \ - } while (0) -#define timersub(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ - if ((vvp)->tv_usec < 0) { \ - (vvp)->tv_sec--; \ - (vvp)->tv_usec += 1000000; \ - } \ - } while (0) -#endif -#endif - -/* - * 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]; -}; - -static enum clnt_stat -clntudp_a_call(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 */ -{ - struct cu_data *cu = (struct cu_data *)cl->cl_private; - XDR *xdrs; - int outlen = 0; - 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); - if (xargs == NULL) - goto get_reply; - xdrs->x_op = XDR_ENCODE; - XDR_SETPOS(xdrs, cu->cu_xdrpos); - /* - * the transaction is the first thing in the out buffer - */ - (*(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); - } - -get_reply: - - /* - * sub-optimal code appears here because we have - * some clock time to spare while the packets are in flight. - * (We assume that this is actually only executed once.) - */ - reply_msg.acpted_rply.ar_verf = _null_auth; - reply_msg.acpted_rply.ar_results.where = resultsp; - reply_msg.acpted_rply.ar_results.proc = xresults; - - 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; -#ifdef dont_check_xid - /* see if reply transaction id matches sent id */ - if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf))) - continue; -#endif - /* 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; - 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 { - cu->cu_error.re_status = RPC_CANTDECODERES; - } - if (fds != &readfds) - free(fds); - return (cu->cu_error.re_status); -} +#include "yp_ping.h" /* * pmap_getport.c @@ -337,8 +108,8 @@ static struct timeval tottimeout = { 1, 0 }; * Returns 0 if no map exists. */ static u_short -__pmap_getport(struct sockaddr_in *address, - u_long program, u_long version, u_int protocol) +__pmap_getport(struct sockaddr_in *address, u_long program, u_long version, + u_int protocol) { u_short port = 0; int sock = -1; @@ -354,8 +125,10 @@ __pmap_getport(struct sockaddr_in *address, 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, 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) { @@ -431,24 +204,23 @@ ypproc_domain_nonack_2_recv(domainname *argp, CLIENT *clnt) struct ping_req { struct sockaddr_in sin; - unsigned long xid; + u_int32_t xid; }; int -__yp_ping(struct in_addr *restricted_addrs, int cnt, - char *dom, short int *port) +__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port) { struct timeval tv = { 5, 0 }; struct ping_req **reqs; unsigned long i; + int async; struct sockaddr_in sin, *any = NULL; + struct netbuf addr; int winner = -1; - time_t xid_seed, xid_lookup; + u_int32_t xid_seed, xid_lookup; int sock, dontblock = 1; CLIENT *clnt; char *foo = dom; - struct cu_data *cu; - enum clnt_stat (*oldfunc)(); int validsrvs = 0; /* Set up handles. */ @@ -490,20 +262,20 @@ __yp_ping(struct in_addr *restricted_addrs, int cnt, return(-1); } 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); + async = TRUE; + clnt_control(clnt, CLSET_ASYNC, (char *)&async); ioctl(sock, FIONBIO, &dontblock); - oldfunc = clnt->cl_ops->cl_call; - clnt->cl_ops->cl_call = clntudp_a_call; /* Transmit */ for (i = 0; i < cnt; i++) { if (reqs[i] != NULL) { - /* subtract one; clntudp_call() will increment */ - *((u_int32_t *)(cu->cu_outbuf)) = reqs[i]->xid - 1; - bcopy((char *)&reqs[i]->sin, (char *)&cu->cu_raddr, - sizeof(struct sockaddr_in)); + clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); + addr.len = sizeof(reqs[i]->sin); + addr.buf = (char *) &reqs[i]->sin; + clnt_control(clnt, CLSET_SVC_ADDR, &addr); ypproc_domain_nonack_2_send(&foo, clnt); } } @@ -512,7 +284,7 @@ __yp_ping(struct in_addr *restricted_addrs, int cnt, ypproc_domain_nonack_2_recv(&foo, clnt); /* Got a winner -- look him up. */ - xid_lookup = *((u_int32_t *)(cu->cu_inbuf)); + clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); for (i = 0; i < cnt; i++) { if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { winner = i; @@ -521,7 +293,6 @@ __yp_ping(struct in_addr *restricted_addrs, int cnt, } /* Shut everything down */ - clnt->cl_ops->cl_call = oldfunc; auth_destroy(clnt->cl_auth); clnt_destroy(clnt); close(sock); diff --git a/usr.sbin/ypbind/ypbind.8 b/usr.sbin/ypbind/ypbind.8 index 1f67e540cb..6cb8666105 100644 --- a/usr.sbin/ypbind/ypbind.8 +++ b/usr.sbin/ypbind/ypbind.8 @@ -9,10 +9,6 @@ .\" 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. @@ -29,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/ypbind/ypbind.8,v 1.15.2.4 2003/03/11 22:31:35 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/ypbind/ypbind.8,v 1.23 2005/02/13 22:25:33 ru Exp $ .\" $DragonFly: src/usr.sbin/ypbind/ypbind.8,v 1.2 2003/06/17 04:30:04 dillon Exp $ .\" .Dd April 9, 1995 @@ -114,7 +110,7 @@ if they originated from the local host. Cause .Nm to run in secure mode: it will refuse to bind to any NIS server -that is not running as root (i.e. that is not using privileged +that is not running as root (i.e., that is not using privileged TCP ports). .It Fl S Xo .Sm off @@ -140,10 +136,11 @@ options, which are often considered to be security holes. The specified servers must have valid entries in the local .Pa /etc/hosts -file. IP addresses may be specified in place of hostnames. +file. +IP addresses may be specified in place of hostnames. If .Nm -can't make sense ouf of the arguments, it will ignore +cannot make sense out of the arguments, it will ignore the .Fl S flag and continue running normally. diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c index bae325a87a..c01eccf493 100644 --- a/usr.sbin/ypbind/ypbind.c +++ b/usr.sbin/ypbind/ypbind.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypbind/ypbind.c,v 1.30.2.2 2002/02/15 00:46:59 des Exp $ + * $FreeBSD: src/usr.sbin/ypbind/ypbind.c,v 1.40 2004/10/17 19:33:33 stefanf Exp $ * $DragonFly: src/usr.sbin/ypbind/ypbind.c,v 1.6 2005/11/24 22:23:02 swildner Exp $ */ @@ -61,7 +61,6 @@ #include #include #include -struct dom_binding{}; #include #include "yp_ping.h" @@ -158,8 +157,8 @@ ypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) { static char res; - bzero((char *)&res, sizeof(res)); - return (void *)&res; + bzero(&res, sizeof(res)); + return &res; } struct ypbind_resp * @@ -169,7 +168,7 @@ ypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) struct _dom_binding *ypdb; char path[MAXPATHLEN]; - bzero((char *)&res, sizeof res); + bzero(&res, sizeof res); res.ypbind_status = YPBIND_FAIL_VAL; res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; @@ -202,7 +201,7 @@ rejecting.", *argp); res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; return (&res); } - bzero((char *)ypdb, sizeof *ypdb); + bzero(ypdb, sizeof *ypdb); strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); ypdb->dom_vers = YPVERS; ypdb->dom_alive = 0; @@ -270,7 +269,7 @@ rejecting.", argp->ypsetdom_domain); return(NULL); } - bzero((char *)&bindsin, sizeof bindsin); + bzero(&bindsin, sizeof bindsin); bindsin.sin_family = AF_INET; bindsin.sin_addr.s_addr = *(u_int32_t *)argp->ypsetdom_binding.ypbind_binding_addr; bindsin.sin_port = *(u_short *)argp->ypsetdom_binding.ypbind_binding_port; @@ -279,7 +278,7 @@ rejecting.", argp->ypsetdom_domain); return((void *) &result); } -static void +void ypbindprog_2(struct svc_req *rqstp, SVCXPRT *transp) { union { @@ -327,13 +326,14 @@ ypbindprog_2(struct svc_req *rqstp, SVCXPRT *transp) svcerr_noproc(transp); return; } - bzero((char *)&argument, sizeof(argument)); - if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { + bzero(&argument, sizeof(argument)); + if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { svcerr_decode(transp); return; } result = (*local)(transp, &argument, rqstp); - if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + if (result != NULL && + !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { svcerr_systemerr(transp); } return; @@ -401,9 +401,11 @@ main(int argc, char **argv) else if (strcmp("-s", argv[i]) == 0) ypsecuremode++; else if (strcmp("-S", argv[i]) == 0 && argc > i) - yp_restricted_mode(argv[i+1]); + yp_restricted_mode(argv[++i]); else if (strcmp("-m", argv[i]) == 0) yp_manycast++; + else + errx(1, "unknown option: %s", argv[i]); } /* blow away everything in BINDINGDIR (if it exists) */ @@ -445,7 +447,7 @@ main(int argc, char **argv) ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); if (ypbindlist == NULL) errx(1, "malloc"); - bzero((char *)ypbindlist, sizeof *ypbindlist); + bzero(ypbindlist, sizeof *ypbindlist); strncpy(ypbindlist->dom_domain, domain_name, sizeof ypbindlist->dom_domain); ypbindlist->dom_vers = YPVERS; ypbindlist->dom_alive = 0; @@ -536,7 +538,7 @@ handle_children(struct _dom_binding *ypdb) FD_CLR(READFD, &svc_fdset); READFD = WRITEFD = -1; if (d > 0 && a > 0) - rpc_received((char *)&buf, &addr, 0); + rpc_received(buf, &addr, 0); else { for (y = ypbindlist; y; y = y->dom_pnext) { if (y == ypdb) @@ -607,10 +609,10 @@ tell_parent(char *dom, struct sockaddr_in *addr) } bool_t -broadcast_result(caddr_t out, struct sockaddr_in *addr) +broadcast_result(bool_t *out, struct sockaddr_in *addr) { if (retries >= MAX_RETRIES) { - bzero((char *)addr, sizeof(struct sockaddr_in)); + bzero(addr, sizeof(struct sockaddr_in)); if (tell_parent(broad_domain->dom_domain, addr)) syslog(LOG_WARNING, "lost connection to parent"); return (TRUE); @@ -699,15 +701,17 @@ broadcast(struct _dom_binding *ypdb) i = __yp_ping(restricted_addrs, yp_restricted, ypdb->dom_domain, &port); if (i == -1) { - bzero((char *)&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); + bzero(&ypdb->dom_server_addr, + sizeof(struct sockaddr_in)); if (tell_parent(ypdb->dom_domain, - &ypdb->dom_server_addr)) - syslog(LOG_WARNING, "lost connection to parent"); + &ypdb->dom_server_addr)) { + syslog(LOG_WARNING, + "lost connection to parent"); + } } else { - bzero((char *)&sin, sizeof(struct sockaddr_in)); - bcopy((char *)&restricted_addrs[i], - (char *)&sin.sin_addr, sizeof(struct in_addr)); + bzero(&sin, sizeof(struct sockaddr_in)); + bcopy(&restricted_addrs[i], + &sin.sin_addr, sizeof(struct in_addr)); sin.sin_family = AF_INET; sin.sin_port = port; if (tell_parent(broad_domain->dom_domain, &sin)) @@ -722,15 +726,15 @@ broadcast(struct _dom_binding *ypdb) { char *ptr; - ptr = (char *)&ypdb->dom_domain; + ptr = ypdb->dom_domain; stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, - xdr_domainname, (char *)&ptr, xdr_bool, (char *)&out, - broadcast_result); + (xdrproc_t)xdr_domainname, &ptr, + (xdrproc_t)xdr_bool, &out, + (resultproc_t)broadcast_result); } if (stat != RPC_SUCCESS) { - bzero((char *)&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); + bzero(&ypdb->dom_server_addr, sizeof(struct sockaddr_in)); if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) syslog(LOG_WARNING, "lost connection to parent"); } @@ -780,11 +784,12 @@ ping(struct _dom_binding *ypdb) { char *ptr; - ptr = (char *)&ypdb->dom_domain; + ptr = ypdb->dom_domain; - if ((stat = clnt_call(client_handle, YPPROC_DOMAIN, - xdr_domainname, (char *)&ptr, xdr_bool, (char *)&out, - timeout)) != RPC_SUCCESS || out == FALSE) { + stat = clnt_call(client_handle, YPPROC_DOMAIN, + (xdrproc_t)xdr_domainname, &ptr, + (xdrproc_t)xdr_bool, &out, timeout); + if (stat != RPC_SUCCESS || out == FALSE) { ypdb->dom_alive = 0; ypdb->dom_vers = -1; clnt_destroy(client_handle); @@ -872,7 +877,7 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force) syslog(LOG_WARNING, "malloc: %m"); return; } - bzero((char *)ypdb, sizeof *ypdb); + bzero(ypdb, sizeof *ypdb); strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); ypdb->dom_lockfd = -1; ypdb->dom_default = 0; @@ -885,8 +890,7 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force) syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK", inet_ntoa(raddrp->sin_addr), ypdb->dom_domain); - bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr, - sizeof ypdb->dom_server_addr); + bcopy(raddrp, &ypdb->dom_server_addr, sizeof ypdb->dom_server_addr); ypdb->dom_vers = YPVERS; ypdb->dom_alive = 1; @@ -918,9 +922,9 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force) */ ypdb->dom_lockfd = fd; - iov[0].iov_base = (caddr_t)&(udptransp->xp_port); + iov[0].iov_base = (char *)&(udptransp->xp_port); iov[0].iov_len = sizeof udptransp->xp_port; - iov[1].iov_base = (caddr_t)&ybr; + iov[1].iov_base = (char *)&ybr; iov[1].iov_len = sizeof ybr; bzero(&ybr, sizeof ybr); @@ -946,8 +950,7 @@ verify(struct in_addr addr) int i; for (i = 0; i < RESTRICTED_SERVERS; i++) - if (!bcmp((char *)&addr, (char *)&restricted_addrs[i], - sizeof(struct in_addr))) + if (!bcmp(&addr, &restricted_addrs[i], sizeof(struct in_addr))) return(0); return(1); @@ -973,9 +976,9 @@ yp_restricted_mode(char *args) while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) { if ((h = gethostbyname(s)) == NULL) return; - bcopy ((char *)h->h_addr_list[0], (char *)&restricted_addrs[i], - sizeof(struct in_addr)); - i++; + bcopy (h->h_addr_list[0], &restricted_addrs[i], + sizeof(struct in_addr)); + i++; } /* ypset and ypsetme not allowed with restricted mode */ diff --git a/usr.sbin/yppush/Makefile b/usr.sbin/yppush/Makefile index 98933dd8f1..2732488336 100644 --- a/usr.sbin/yppush/Makefile +++ b/usr.sbin/yppush/Makefile @@ -1,21 +1,20 @@ -# $FreeBSD: src/usr.sbin/yppush/Makefile,v 1.6.2.1 2001/04/25 12:11:14 ru Exp $ +# $FreeBSD: src/usr.sbin/yppush/Makefile,v 1.9 2001/07/20 06:20:30 obrien Exp $ # $DragonFly: src/usr.sbin/yppush/Makefile,v 1.2 2003/06/17 04:30:04 dillon Exp $ +RPCDIR= ${.CURDIR}/../../include/rpcsvc +.PATH: ${RPCDIR} ${.CURDIR}/../../usr.sbin/ypserv \ + ${.CURDIR}/../../libexec/ypxfr + PROG= yppush +MAN= yppush.8 SRCS= ypxfr_getmap.c yp_dblookup.c yp_error.c ypxfr_misc.c yppush_main.c \ ${GENSRCS} GENSRCS=yp.h yp_clnt.c yppush_svc.c -MAN= yppush.8 +CFLAGS+= -I. -I${.CURDIR}/../../libexec/ypxfr -CFLAGS+=-I. -I${.CURDIR}/../../libexec/ypxfr - -RPCDIR= ${.CURDIR}/../../include/rpcsvc RPCGEN= rpcgen -C -.PATH: ${RPCDIR} ${.CURDIR}/../../usr.sbin/ypserv \ - ${.CURDIR}/../../libexec/ypxfr - CLEANFILES= ${GENSRCS} yppush_svc.c: yp.x diff --git a/usr.sbin/yppush/yppush.8 b/usr.sbin/yppush/yppush.8 index 7c727b279f..6818835d79 100644 --- a/usr.sbin/yppush/yppush.8 +++ b/usr.sbin/yppush/yppush.8 @@ -9,10 +9,6 @@ .\" 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. @@ -29,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/yppush/yppush.8,v 1.12.2.3 2003/03/11 22:31:35 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/yppush/yppush.8,v 1.18 2005/01/18 20:02:45 ru Exp $ .\" $DragonFly: src/usr.sbin/yppush/yppush.8,v 1.4 2006/02/17 19:40:30 swildner Exp $ .\" .Dd February 5, 1995 @@ -75,7 +71,8 @@ By default, .Nm determines the names of the slave servers for a domain by searching the .Pa ypservers -map. A destination host (or a list of hosts) can also be manually +map. +A destination host (or a list of hosts) can also be manually specified on the command line. Once it has a complete list of slave servers, it sends a 'map transfer' request to each slave, which in turn reads a copy of the map from @@ -141,7 +138,8 @@ Can be used to transfer a map to a user-specified machine or group of machines instead of the list of servers contained in the .Pa ypservers -map. A list of hosts can be specified by using multiple +map. +A list of hosts can be specified by using multiple instances of the .Fl h flag. @@ -177,6 +175,7 @@ a particular NIS domain .An Bill Paul Aq wpaul@ctr.columbia.edu .Sh BUGS The mechanism for transferring NIS maps in NIS v1 is different -than that in NIS version 2. This version of +than that in NIS version 2. +This version of .Nm has support for transferring maps to NIS v2 systems only. diff --git a/usr.sbin/yppush/yppush_main.c b/usr.sbin/yppush/yppush_main.c index 2b07396a5b..88d59ddff8 100644 --- a/usr.sbin/yppush/yppush_main.c +++ b/usr.sbin/yppush/yppush_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/yppush/yppush_main.c,v 1.11.2.2 2002/02/15 00:46:59 des Exp $ + * $FreeBSD: src/usr.sbin/yppush/yppush_main.c,v 1.22 2006/08/16 12:58:41 thomas Exp $ * $DragonFly: src/usr.sbin/yppush/yppush_main.c,v 1.3 2005/11/24 22:23:02 swildner Exp $ */ @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ #include #include #include -struct dom_binding {}; #include #include "ypxfr_extern.h" #include "yppush_extern.h" @@ -61,17 +61,16 @@ char *yp_dir = _PATH_YP; char *yppush_mapname = NULL; /* Map to transfer. */ char *yppush_domain = NULL; /* Domain in which map resides. */ char *yppush_master = NULL; /* Master NIS server for said domain. */ +int skip_master = 0; /* Do not attempt to push map to master. */ int verbose = 0; /* Toggle verbose mode. */ unsigned long yppush_transid = 0; int yppush_timeout = 80; /* Default timeout. */ -int yppush_jobs = 0; /* Number of allowed concurrent jobs. */ +int yppush_jobs = 1; /* Number of allowed concurrent jobs. */ int yppush_running_jobs = 0; /* Number of currently running jobs. */ -int yppush_alarm_tripped = 0; /* Structure for holding information about a running job. */ struct jobs { unsigned long tid; - int sock; int port; ypxfrstat stat; unsigned long prognum; @@ -83,18 +82,25 @@ struct jobs { struct jobs *yppush_joblist; /* Linked list of running jobs. */ +static int yppush_svc_run(int); + /* * Local error messages. */ -static char * +static const char * yppusherr_string(int err) { switch (err) { - case YPPUSH_TIMEDOUT: return("transfer or callback timed out"); - case YPPUSH_YPSERV: return("failed to contact ypserv"); - case YPPUSH_NOHOST: return("no such host"); - case YPPUSH_PMAP: return("portmapper failure"); - default: return("unknown error code"); + case YPPUSH_TIMEDOUT: + return("transfer or callback timed out"); + case YPPUSH_YPSERV: + return("failed to contact ypserv"); + case YPPUSH_NOHOST: + return("no such host"); + case YPPUSH_PMAP: + return("portmapper failure"); + default: + return("unknown error code"); } } @@ -108,19 +114,29 @@ yppush_show_status(ypxfrstat status, unsigned long tid) job = yppush_joblist; - while (job) { + while (job != NULL) { if (job->tid == tid) break; job = job->next; } + if (job == NULL) { + yp_error("warning: received callback with invalid transaction ID: %lu", + tid); + return (0); + } + if (job->polled) { - return(0); + yp_error("warning: received callback with duplicate transaction ID: %lu", + tid); + return (0); } - if (verbose > 1) + if (verbose > 1) { yp_error("checking return status: transaction ID: %lu", job->tid); + } + if (status != YPPUSH_SUCC || verbose) { yp_error("transfer of map %s to server %s %s", job->map, job->server, status == YPPUSH_SUCC ? @@ -167,11 +183,7 @@ yppush_exit(int now) yp_error("%d transfer%sstill pending", still_pending, still_pending > 1 ? "s " : " "); - yppush_alarm_tripped = 0; - alarm(YPPUSH_RESPONSE_TIMEOUT); - pause(); - alarm(0); - if (yppush_alarm_tripped == 1) { + if (yppush_svc_run (YPPUSH_RESPONSE_TIMEOUT) == 0) { yp_error("timed out"); now = 1; } @@ -203,42 +215,31 @@ to %s (transid = %lu) still pending", jptr->server, jptr->tid); static void handler(int sig) { - if (sig == SIGTERM || sig == SIGINT || sig == SIGABRT) { - yppush_jobs = 0; - yppush_exit(1); - } - - if (sig == SIGALRM) { - alarm(0); - yppush_alarm_tripped++; - } - + yppush_exit (1); return; } /* * Dispatch loop for callback RPC services. + * Return value: + * -1 error + * 0 timeout + * >0 request serviced */ -static void -yppush_svc_run(void) +static int +yppush_svc_run(int timeout_secs) { -#ifdef FD_SETSIZE + int rc; fd_set readfds; -#else - int readfds; -#endif /* def FD_SETSIZE */ struct timeval timeout; timeout.tv_usec = 0; - timeout.tv_sec = 5; + timeout.tv_sec = timeout_secs; retry: -#ifdef FD_SETSIZE readfds = svc_fdset; -#else - readfds = svc_fds; -#endif /* def FD_SETSIZE */ - switch (select(_rpc_dtablesize(), &readfds, NULL, NULL, &timeout)) { + rc = select(svc_maxfd + 1, &readfds, NULL, NULL, &timeout); + switch (rc) { case -1: if (errno == EINTR) goto retry; @@ -251,25 +252,7 @@ retry: svc_getreqset(&readfds); break; } - return; -} - -/* - * Special handler for asynchronous socket I/O. We mark the - * sockets of the callback handlers as O_ASYNC and handle SIGIO - * events here, which will occur when the callback handler has - * something interesting to tell us. - */ -static void -async_handler(int sig) -{ - yppush_svc_run(); - - /* reset any pending alarms. */ - alarm(0); - yppush_alarm_tripped++; - kill(getpid(), SIGALRM); - return; + return rc; } /* @@ -390,9 +373,17 @@ yp_push(char *server, char *map, unsigned long tid) SVCXPRT *xprt; struct jobs *job; + /* Register the job in our linked list of jobs. */ + + /* First allocate job structure */ + if ((job = (struct jobs *)malloc(sizeof (struct jobs))) == NULL) { + yp_error("malloc failed"); + yppush_exit (1); + } + /* - * Register the callback service on the first free - * transient program number. + * Register the callback service on the first free transient + * program number. */ xprt = svcudp_create(sock); for (prognum = 0x40000000; prognum < 0x5FFFFFFF; prognum++) { @@ -400,18 +391,15 @@ yp_push(char *server, char *map, unsigned long tid) yppush_xfrrespprog_1, IPPROTO_UDP) == TRUE) break; } - - /* Register the job in our linked list of jobs. */ - if ((job = (struct jobs *)malloc(sizeof (struct jobs))) == NULL) { - yp_error("malloc failed"); - yppush_exit(1); + if (prognum == 0x5FFFFFFF) { + yp_error ("can't register yppush_xfrrespprog_1"); + yppush_exit (1); } /* Initialize the info for this job. */ job->stat = 0; job->tid = tid; job->port = xprt->xp_port; - job->sock = xprt->xp_sock; /*XXX: Evil!! EEEEEEEVIL!!! */ job->server = strdup(server); job->map = strdup(map); job->prognum = prognum; @@ -419,27 +407,6 @@ yp_push(char *server, char *map, unsigned long tid) job->next = yppush_joblist; yppush_joblist = job; - /* - * Set the RPC sockets to asynchronous mode. This will - * cause the system to smack us with a SIGIO when an RPC - * callback is delivered. This in turn allows us to handle - * the callback even though we may be in the middle of doing - * something else at the time. - * - * XXX This is a horrible thing to do for two reasons, - * both of which have to do with portability: - * 1) We really ought not to be sticking our grubby mits - * into the RPC service transport handle like this. - * 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) { - yp_error("failed to set async I/O mode: %s", - strerror(errno)); - yppush_exit(1); - } - if (verbose) { yp_error("initiating transfer: %s -> %s (transid = %lu)", yppush_mapname, server, tid); @@ -447,7 +414,7 @@ yp_push(char *server, char *map, unsigned long tid) /* * Send the XFR request to ypserv. We don't have to wait for - * a response here since we can handle them asynchronously. + * a response here since we handle them asynchronously. */ if (yppush_send_xfr(job)){ @@ -476,32 +443,19 @@ yppush_foreach(int status, char *key, int keylen, char *val, int vallen, return (status); snprintf(server, sizeof(server), "%.*s", vallen, val); + if (skip_master && strcasecmp(server, yppush_master) == 0) + return (0); /* - * Restrict the number of concurrent jobs. If yppush_jobs number + * Restrict the number of concurrent jobs: if yppush_jobs number * of jobs have already been dispatched and are still pending, * wait for one of them to finish so we can reuse its slot. */ - if (yppush_jobs <= 1) { - yppush_alarm_tripped = 0; - while (!yppush_alarm_tripped && yppush_running_jobs) { - alarm(yppush_timeout); - yppush_alarm_tripped = 0; - pause(); - alarm(0); - } - } else { - yppush_alarm_tripped = 0; - while (!yppush_alarm_tripped && yppush_running_jobs >= yppush_jobs) { - alarm(yppush_timeout); - yppush_alarm_tripped = 0; - pause(); - alarm(0); - } - } + while (yppush_running_jobs >= yppush_jobs && (yppush_svc_run (yppush_timeout) > 0)) + ; /* Cleared for takeoff: set everything in motion. */ - if (yp_push(&server, yppush_mapname, yppush_transid)) + if (yp_push(server, yppush_mapname, yppush_transid)) return(yp_errno); /* Bump the job counter and transaction ID. */ @@ -612,7 +566,13 @@ main(int argc, char *argv[]) yppush_exit(1); } - if (strncmp(myname, data.data, data.size)) { + if (strncasecmp(myname, data.data, data.size) == 0) { + /* I am master server, and no explicit host list was + specified: do not push map to myself -- this will + fail with YPPUSH_AGE anyway. */ + if (yppush_hostlist == NULL) + skip_master = 1; + } else { yp_error("warning: this host is not the master for %s", yppush_mapname); #ifdef NITPICKY @@ -625,29 +585,11 @@ main(int argc, char *argv[]) yppush_master[data.size] = '\0'; /* Install some handy handlers. */ - signal(SIGALRM, handler); signal(SIGTERM, handler); signal(SIGINT, handler); - signal(SIGABRT, handler); - - /* - * Set up the SIGIO handler. Make sure that some of the - * other signals are blocked while the handler is running so - * select() doesn't get interrupted. - */ - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGIO); /* Goes without saying. */ - sigaddset(&sa.sa_mask, SIGPIPE); - sigaddset(&sa.sa_mask, SIGCHLD); - sigaddset(&sa.sa_mask, SIGALRM); - sigaddset(&sa.sa_mask, SIGINT); - sa.sa_handler = async_handler; - sa.sa_flags = 0; - - sigaction(SIGIO, &sa, NULL); /* set initial transaction ID */ - yppush_transid = time((time_t *)NULL); + yppush_transid = time(NULL); if (yppush_hostlist) { /* diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile index 4466b7bd1c..44cc8b05b2 100644 --- a/usr.sbin/ypserv/Makefile +++ b/usr.sbin/ypserv/Makefile @@ -1,19 +1,21 @@ -# $FreeBSD: src/usr.sbin/ypserv/Makefile,v 1.17.2.3 2002/08/07 16:32:02 ru Exp $ +# $FreeBSD: src/usr.sbin/ypserv/Makefile,v 1.24 2004/10/18 21:42:15 ru Exp $ # $DragonFly: src/usr.sbin/ypserv/Makefile,v 1.3 2005/07/07 11:49:57 corecode Exp $ +RPCDIR= ${.CURDIR}/../../include/rpcsvc +.PATH: ${RPCDIR} + PROG= ypserv +MAN= ypserv.8 ypinit.8 SRCS= yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \ ypxfr_clnt.c yp.h yp_main.c yp_error.c yp_access.c yp_svc_udp.c -MAN= ypserv.8 ypinit.8 +CFLAGS+= -DDB_CACHE -DTCP_WRAPPER -I. -CFLAGS+= -I. -DDB_CACHE +DPADD= ${LIBWRAP} +LDADD= -lwrap CLEANFILES= yp_svc.c ypxfr_clnt.c yp.h -RPCDIR= ${.CURDIR}/../../include/rpcsvc -.PATH: ${RPCDIR} - RPCGEN= rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that @@ -29,14 +31,13 @@ ypxfr_clnt.c: yp.x yp.h: yp.x ${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/yp.x -afterinstall: - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.CURDIR}/Makefile.yp \ - ${DESTDIR}/var/yp/Makefile.dist - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 555 \ - ${.CURDIR}/ypinit.sh ${DESTDIR}${BINDIR}/ypinit - @if [ ! -f ${DESTDIR}/var/yp/Makefile.dist ]; then \ - ${LN} -s ${DESTDIR}/var/yp/Makefile.dist \ - ${DESTDIR}/var/yp/Makefile; fi +FILES= Makefile.yp +FILESNAME= Makefile.dist +FILESDIR= /var/yp +SCRIPTS= ypinit.sh + +.if !exists(${DESTDIR}${FILESDIR}/Makefile) +SYMLINKS= ${FILESNAME} ${FILESDIR}/Makefile +.endif .include diff --git a/usr.sbin/ypserv/Makefile.yp b/usr.sbin/ypserv/Makefile.yp index 16b74f668f..571f18e169 100644 --- a/usr.sbin/ypserv/Makefile.yp +++ b/usr.sbin/ypserv/Makefile.yp @@ -1,7 +1,7 @@ # # Makefile for the NIS databases # -# $FreeBSD: src/usr.sbin/ypserv/Makefile.yp,v 1.28.2.3 2001/05/18 18:28:02 gshapiro Exp $ +# $FreeBSD: src/usr.sbin/ypserv/Makefile.yp,v 1.38 2006/06/08 09:12:07 maxim Exp $ # $DragonFly: src/usr.sbin/ypserv/Makefile.yp,v 1.3 2004/01/08 18:39:19 asmodai Exp $ # # This Makefile should only be run on the NIS master server of a domain. @@ -50,8 +50,6 @@ AWK = /usr/bin/awk RM = @/bin/rm -f MV = @/bin/mv -f RMV = /bin/mv -f -RCAT = /bin/cat -CAT = @$(RCAT) MKDB = /usr/sbin/yp_mkdb DBLOAD = $(MKDB) -m `hostname` @@ -101,10 +99,12 @@ YPMAPDIR = $(YPDIR)/$(DOMAIN) ETHERS = $(YPSRCDIR)/ethers # ethernet addresses (for rarpd) BOOTPARAMS= $(YPSRCDIR)/bootparams # for booting Sun boxes (bootparamd) HOSTS = $(YPSRCDIR)/hosts +IPNODES = $(YPDIR)/ipnodes NETWORKS = $(YPSRCDIR)/networks PROTOCOLS = $(YPSRCDIR)/protocols RPC = $(YPSRCDIR)/rpc SERVICES = $(YPSRCDIR)/services +SHELLS = $(YPSRCDIR)/shells GROUP = $(YPSRCDIR)/group ALIASES = $(YPSRCDIR)/mail/aliases NETGROUP = $(YPDIR)/netgroup @@ -117,12 +117,12 @@ MASTER = $(MASTER_PASSWD) YPSERVERS = $(YPDIR)/ypservers # List of all NIS servers for a domain PUBLICKEY = $(YPSRCDIR)/publickey NETID = $(YPSRCDIR)/netid -AMDHOST = $(YPSRCDIR)/amd.host +AMDHOST = $(YPSRCDIR)/amd.map # List of maps that are always built. # If you want to omit some of them, feel free to comment # them out from this list. -TARGETS= servers hosts networks protocols rpc services group +TARGETS= servers hosts networks protocols rpc services shells group #TARGETS+= aliases # Sanity checks: filter out targets we can't build @@ -161,11 +161,17 @@ PUBLICKEY= /dev/null .endif .if exists($(AMDHOST)) -TARGETS+= amd.host +TARGETS+= amd.map .else AMDHOST= /dev/null .endif +.if exists($(IPNODES)) +TARGETS+= ipnodes +.else +IPNODES= /dev/null +.endif + target: @if [ ! -d $(DOMAIN) ]; then mkdir $(DOMAIN); fi; \ cd $(DOMAIN) ; echo "NIS Map update started on `date` for domain $(DOMAIN)" ; \ @@ -176,6 +182,7 @@ all: $(TARGETS) ethers: ethers.byname ethers.byaddr bootparam: bootparams hosts: hosts.byname hosts.byaddr +ipnodes: ipnodes.byname ipnodes.byaddr networks: networks.byaddr networks.byname protocols: protocols.bynumber protocols.byname rpc: rpc.byname rpc.bynumber @@ -233,23 +240,21 @@ mail.aliases: $(ALIASES) ypservers: $(YPSERVERS) @echo "Updating $@..." - $(CAT) $(YPSERVERS) | \ - $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*") print $$0"\t"$$0 }' $^ \ + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*") print $$0"\t"$$0 }' \ + $(YPSERVERS) \ | $(DBLOAD) -i $(YPSERVERS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - ethers.byname: $(ETHERS) @echo "Updating $@..." .if ${ETHERS} == "/dev/null" @echo "Ethers source file not found -- skipping" .else - $(CAT) $(ETHERS) | \ - $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$2"\t"$$0 }' $^ | $(DBLOAD) -i $(ETHERS) \ + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$2"\t"$$0 }' $(ETHERS) | $(DBLOAD) -i $(ETHERS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -261,9 +266,8 @@ ethers.byaddr: $(ETHERS) .if ${ETHERS} == "/dev/null" @echo "Ethers source file not found -- skipping" .else - $(CAT) $(ETHERS) | \ - $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1"\t"$$0 }' $^ | $(DBLOAD) -i $(ETHERS) \ + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$1"\t"$$0 }' $(ETHERS) | $(DBLOAD) -i $(ETHERS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -276,9 +280,8 @@ bootparams: $(BOOTPARAMS) .if ${BOOTPARAMS} == "/dev/null" @echo "Bootparams source file not found -- skipping" .else - $(CAT) $(BOOTPARAMS) | \ - $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$0 }' $^ | $(DBLOAD) -i $(BOOTPARAMS) \ + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$0 }' $(BOOTPARAMS) | $(DBLOAD) -i $(BOOTPARAMS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -291,14 +294,12 @@ netgroup: $(NETGROUP) netgroup.byhost netgroup.byuser .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else - $(CAT) $(NETGROUP) | \ - $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$0 }' $(NETGROUP) | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - @$(MAKE) -f ../Makefile netid .endif @@ -307,9 +308,9 @@ netgroup.byhost: $(NETGROUP) .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else - $(CAT) $(NETGROUP) | $(REVNETGROUP) -h -f $(NETGROUP) | \ + @$(REVNETGROUP) -h -f $(NETGROUP) | \ $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + print $$0 }' | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -322,9 +323,9 @@ netgroup.byuser: $(NETGROUP) .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else - $(CAT) $(NETGROUP) | $(REVNETGROUP) -u -f $(NETGROUP) | \ + @$(REVNETGROUP) -u -f $(NETGROUP) | \ $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + print $$0 }' | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -334,36 +335,60 @@ netgroup.byuser: $(NETGROUP) hosts.byname: $(HOSTS) @echo "Updating $@..." - $(CAT) $(HOSTS) | \ - $(AWK) '/^[0-9]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ - print $$n"\t"$$0 }' $^ | $(DBLOAD) ${B} -i $(HOSTS) \ + @$(AWK) '/^[0-9]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ + print $$n"\t"$$0 }' $(HOSTS) | $(DBLOAD) ${B} -i $(HOSTS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - @$(MAKE) -f ../Makefile netid hosts.byaddr: $(HOSTS) @echo "Updating $@..." - $(CAT) $(HOSTS) | \ - $(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$0 }' $^ \ + @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$0 }' $(HOSTS) \ | $(DBLOAD) ${B} -i $(HOSTS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - @$(MAKE) -f ../Makefile netid + + +ipnodes.byname: $(IPNODES) + @echo "Updating $@..." +.if ${IPNODES} == "/dev/null" + @echo "Ipnodes source file not found -- skipping" +.else + @$(AWK) '/^[0-9a-fA-F:]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ + print $$n"\t"$$0 }' $(IPNODES) | $(DBLOAD) ${B} -i $(IPNODES) \ + -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ + @$(DBLOAD) -c + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi +.endif + + +ipnodes.byaddr: $(IPNODES) + @echo "Updating $@..." +.if ${IPNODES} == "/dev/null" + @echo "Ipnodes source file not found -- skipping" +.else + @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$0 }' $(IPNODES) \ + | $(DBLOAD) ${B} -i $(IPNODES) -o $(YPMAPDIR)/$@ - $(TMP); \ + $(RMV) $(TMP) $@ + @$(DBLOAD) -c + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi +.endif networks.byname: $(NETWORKS) @echo "Updating $@..." - $(CAT) $(NETWORKS) | \ - $(AWK) \ + @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ - }' $^ | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $(TMP); \ + }' $(NETWORKS) \ + | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -372,8 +397,7 @@ networks.byname: $(NETWORKS) networks.byaddr: $(NETWORKS) @echo "Updating $@..." - $(CAT) $(NETWORKS) | \ - $(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $^ \ + @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(NETWORKS) \ | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -383,12 +407,11 @@ networks.byaddr: $(NETWORKS) protocols.byname: $(PROTOCOLS) @echo "Updating $@..." - $(CAT) $(PROTOCOLS) | \ - $(AWK) \ + @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ - }' $^ | $(DBLOAD) -i $(PROTOCOLS) \ + }' $(PROTOCOLS) | $(DBLOAD) -i $(PROTOCOLS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -397,8 +420,7 @@ protocols.byname: $(PROTOCOLS) protocols.bynumber: $(PROTOCOLS) @echo "Updating $@..." - $(CAT) $(PROTOCOLS) | \ - $(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $^ \ + @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(PROTOCOLS) \ | $(DBLOAD) -i $(PROTOCOLS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -408,12 +430,11 @@ protocols.bynumber: $(PROTOCOLS) rpc.byname: $(RPC) @echo "Updating $@..." - $(CAT) $(RPC) | \ - $(AWK) \ + @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ - }' $^ | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $(TMP); \ + }' $(RPC) | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @@ -422,8 +443,7 @@ rpc.byname: $(RPC) rpc.bynumber: $(RPC) @echo "Updating $@..." - $(CAT) $(RPC) | \ - $(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $^ \ + @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(RPC) \ | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -433,28 +453,36 @@ rpc.bynumber: $(RPC) services.byname: $(SERVICES) @echo "Updating $@..." - $(CAT) $(SERVICES) | \ - $(AWK) \ + @$(AWK) \ '$$1 !~ "^#.*" { for (n=1; n<=NF && $$n !~ "^#.*"; n++) { \ if (split($$2, t, "/")) { \ printf("%s/%s", $$n, t[2]) }; \ print "\t"$$0; \ if (n == 1) n = 2; \ } ; print $$2"\t"$$0 ; \ - }' $^ | $(DBLOAD) -i $(SERVICES) -o $(YPMAPDIR)/$@ - $(TMP); \ + }' $(SERVICES) \ + | $(DBLOAD) -i $(SERVICES) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi +shells: $(SHELLS) + @echo "Updating $@..." + @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*") print $$0"\t"$$0 }' \ + $(SHELLS) \ + | $(DBLOAD) -i $(SHELLS) -o $(YPMAPDIR)/$@ - $(TMP); \ + $(RMV) $(TMP) $@ + @$(DBLOAD) -c + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi publickey.byname: $(PUBLICKEY) @echo "Updating $@..." .if ${PUBLICKEY} == "/dev/null" @echo "Publickey source file not found -- skipping" .else - $(CAT) $(PUBLICKEY) | \ - $(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$2 }' $^ \ + @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$2 }' $(PUBLICKEY) \ | $(DBLOAD) -i $(PUBLICKEY) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -466,21 +494,19 @@ publickey.byname: $(PUBLICKEY) $(PASSWD): $(MASTER) @echo "Creating new $@ file from $(MASTER)..." @if [ ! $(UNSECURE) ]; then \ - $(RCAT) $(MASTER) | \ $(AWK) -F: '{if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1":*:"$$3":"$$4":"$$8":"$$9":"$$10}' $^ \ + print $$1":*:"$$3":"$$4":"$$8":"$$9":"$$10}' $(MASTER) \ > $(PASSWD) ; \ - else $(RCAT) $(MASTER) | \ + else \ $(AWK) -F: '{if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1":"$$2":"$$3":"$$4":"$$8":"$$9":"$$10}' $^ \ + print $$1":"$$2":"$$3":"$$4":"$$8":"$$9":"$$10}' $(MASTER) \ > $(PASSWD) ; fi passwd.byname: $(PASSWD) @echo "Updating $@..." - $(CAT) $(PASSWD) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$1"\t"$$0 }' $(PASSWD) \ | $(DBLOAD) -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -490,22 +516,19 @@ passwd.byname: $(PASSWD) passwd.byuid: $(PASSWD) @echo "Updating $@..." - $(CAT) $(PASSWD) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$3"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$3"\t"$$0 }' $(PASSWD) \ | $(DBLOAD) -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - @$(MAKE) -f ../Makefile netid group.byname: $(GROUP) @echo "Updating $@..." - $(CAT) $(GROUP) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$1"\t"$$0 }' $(GROUP) \ | $(DBLOAD) -f -i $(GROUP) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -515,18 +538,16 @@ group.byname: $(GROUP) group.bygid: $(GROUP) @echo "Updating $@..." - $(CAT) $(GROUP) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$3"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$3"\t"$$0 }' $(GROUP) \ | $(DBLOAD) -f -i $(GROUP) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi - @$(MAKE) -f ../Makefile netid -netid.byname: $(GROUP) $(PASSWD) +netid.byname: $(GROUP) $(PASSWD) $(HOSTS) @echo "Updating $@..." @$(MKNETID) -q -p $(PASSWD) -g $(GROUP) -h $(HOSTS) -n $(NETID) \ -d $(DOMAIN) | $(DBLOAD) -o $(YPMAPDIR)/$@ - $(TMP); \ @@ -541,9 +562,8 @@ master.passwd.byname: $(MASTER) .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else - $(CAT) $(MASTER) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$1"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$1"\t"$$0 }' $(MASTER) \ | $(DBLOAD) ${S} -f -i $(MASTER) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -557,9 +577,8 @@ master.passwd.byuid: $(MASTER) .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else - $(CAT) $(MASTER) | \ - $(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ - print $$3"\t"$$0 }' $^ \ + @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ + print $$3"\t"$$0 }' $(MASTER) \ | $(DBLOAD) ${S} -f -i $(MASTER) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @@ -568,10 +587,9 @@ master.passwd.byuid: $(MASTER) .endif -amd.host: $(AMDHOST) +amd.map: $(AMDHOST) @echo "Updating $@..." - $(CAT) $(AMDHOST) | \ - $(AWK) '$$1 !~ "^#.*" { \ + @$(AWK) '$$1 !~ "^#.*" { \ for (i = 1; i <= NF; i++) \ if (i == NF) { \ if (substr($$i, length($$i), 1) == "\\") \ @@ -581,7 +599,7 @@ amd.host: $(AMDHOST) } \ else \ printf("%s ", $$i); \ - }' | \ + }' $(AMDHOST) | \ $(DBLOAD) -i $(AMDHOST) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c diff --git a/usr.sbin/ypserv/yp_access.c b/usr.sbin/ypserv/yp_access.c index 604655d33f..d2b8430ff0 100644 --- a/usr.sbin/ypserv/yp_access.c +++ b/usr.sbin/ypserv/yp_access.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_access.c,v 1.17.2.1 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_access.c,v 1.23 2006/05/31 22:31:08 cperciva Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_access.c,v 1.5 2006/06/13 12:38:37 corecode Exp $ */ @@ -57,33 +57,34 @@ extern int debug; /* NIS v1 */ -char *yp_procs[] = { "ypoldproc_null", - "ypoldproc_domain", - "ypoldproc_domain_nonack", - "ypoldproc_match", - "ypoldproc_first", - "ypoldproc_next", - "ypoldproc_poll", - "ypoldproc_push", - "ypoldproc_get", - "badproc1", /* placeholder */ - "badproc2", /* placeholder */ - "badproc3", /* placeholder */ - - /* NIS v2 */ - "ypproc_null", - "ypproc_domain", - "ypproc_domain_nonack", - "ypproc_match", - "ypproc_first", - "ypproc_next", - "ypproc_xfr", - "ypproc_clear", - "ypproc_all", - "ypproc_master", - "ypproc_order", - "ypproc_maplist" - }; +const char *yp_procs[] = { + "ypoldproc_null", + "ypoldproc_domain", + "ypoldproc_domain_nonack", + "ypoldproc_match", + "ypoldproc_first", + "ypoldproc_next", + "ypoldproc_poll", + "ypoldproc_push", + "ypoldproc_get", + "badproc1", /* placeholder */ + "badproc2", /* placeholder */ + "badproc3", /* placeholder */ + + /* NIS v2 */ + "ypproc_null", + "ypproc_domain", + "ypproc_domain_nonack", + "ypproc_match", + "ypproc_first", + "ypproc_next", + "ypproc_xfr", + "ypproc_clear", + "ypproc_all", + "ypproc_master", + "ypproc_order", + "ypproc_maplist" +}; struct securenet { struct in_addr net; @@ -216,12 +217,13 @@ yp_access(const char *map, const struct svc_req *rqstp) #endif static unsigned long oldaddr = 0; struct securenet *tmp; - char *yp_procedure = NULL; + const char *yp_procedure = NULL; char procbuf[50]; if (rqstp->rq_prog != YPPASSWDPROG && rqstp->rq_prog != YPPROG) { - snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu", rqstp->rq_prog, - rqstp->rq_proc); + snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu", + (unsigned long)rqstp->rq_prog, + (unsigned long)rqstp->rq_proc); yp_procedure = (char *)&procbuf; } else { yp_procedure = rqstp->rq_prog == YPPASSWDPROG ? diff --git a/usr.sbin/ypserv/yp_dblookup.c b/usr.sbin/ypserv/yp_dblookup.c index a1f2632d68..e00ece3399 100644 --- a/usr.sbin/ypserv/yp_dblookup.c +++ b/usr.sbin/ypserv/yp_dblookup.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_dblookup.c,v 1.17.2.1 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_dblookup.c,v 1.25 2003/05/03 21:06:42 obrien Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_dblookup.c,v 1.4 2004/12/18 22:48:15 swildner Exp $ */ @@ -77,11 +77,11 @@ struct dbent { int flags; }; -static CIRCLEQ_HEAD(circlehead, circleq_entry) qhead; +static TAILQ_HEAD(circlehead, circleq_entry) qhead; struct circleq_entry { struct dbent *dbptr; - CIRCLEQ_ENTRY(circleq_entry) links; + TAILQ_ENTRY(circleq_entry) links; }; /* @@ -90,7 +90,7 @@ struct circleq_entry { void yp_init_dbs(void) { - CIRCLEQ_INIT(&qhead); + TAILQ_INIT(&qhead); } /* @@ -164,8 +164,8 @@ yp_flush(void) { struct circleq_entry *qptr; - qptr = qhead.cqh_last; - CIRCLEQ_REMOVE(&qhead, qptr, links); + qptr = TAILQ_LAST(&qhead, circlehead); + TAILQ_REMOVE(&qhead, qptr, links); yp_free_qent(qptr); numdbs--; } @@ -178,9 +178,9 @@ yp_flush_all(void) { struct circleq_entry *qptr; - while (qhead.cqh_first != (void *)&qhead) { - qptr = qhead.cqh_first; /* save this */ - CIRCLEQ_REMOVE(&qhead, qhead.cqh_first, links); + while (!TAILQ_EMPTY(&qhead)) { + qptr = TAILQ_FIRST(&qhead); /* save this */ + TAILQ_REMOVE(&qhead, qptr, links); yp_free_qent(qptr); } numdbs = 0; @@ -225,8 +225,7 @@ yp_testflag(char *map, char *domain, int flag) strcat(buf, "/"); strcat(buf, map); - for (qptr = qhead.cqh_first; qptr != (void *)&qhead; - qptr = qptr->links.cqe_next) { + TAILQ_FOREACH(qptr, &qhead, links) { if (!strcmp(qptr->dbptr->name, buf)) { if (qptr->dbptr->flags & flag) return(1); @@ -238,7 +237,7 @@ yp_testflag(char *map, char *domain, int flag) if (yp_open_db_cache(domain, map, NULL, 0) == NULL) return(0); - if (qhead.cqh_first->dbptr->flags & flag) + if (TAILQ_FIRST(&qhead)->dbptr->flags & flag) return(1); return(0); @@ -277,7 +276,7 @@ yp_cache_db(DB *dbp, char *name, int size) qptr->dbptr->flags = yp_setflags(dbp); - CIRCLEQ_INSERT_HEAD(&qhead, qptr, links); + TAILQ_INSERT_HEAD(&qhead, qptr, links); numdbs++; return(0); @@ -314,8 +313,7 @@ yp_find_db(const char *name, const char *key, const int size) { struct circleq_entry *qptr; - for (qptr = qhead.cqh_first; qptr != (void *)&qhead; - qptr = qptr->links.cqe_next) { + TAILQ_FOREACH(qptr, &qhead, links) { if (!strcmp(qptr->dbptr->name, name)) { if (size) { if (size != qptr->dbptr->size || @@ -325,9 +323,9 @@ yp_find_db(const char *name, const char *key, const int size) if (qptr->dbptr->size) continue; } - if (qptr != qhead.cqh_first) { - CIRCLEQ_REMOVE(&qhead, qptr, links); - CIRCLEQ_INSERT_HEAD(&qhead, qptr, links); + if (qptr != TAILQ_FIRST(&qhead)) { + TAILQ_REMOVE(&qhead, qptr, links); + TAILQ_INSERT_HEAD(&qhead, qptr, links); } return(qptr->dbptr->dbp); } @@ -357,11 +355,11 @@ yp_open_db_cache(const char *domain, const char *map, const char *key, strcat(buf, "/"); strcat(buf, map); - if ((dbp = yp_find_db((char *)&buf, key, size)) != NULL) { + if ((dbp = yp_find_db(buf, key, size)) != NULL) { return(dbp); } else { if ((dbp = yp_open_db(domain, map)) != NULL) { - if (yp_cache_db(dbp, (char *)&buf, size)) { + if (yp_cache_db(dbp, buf, size)) { dbp->close(dbp); yp_errno = YP_YPERR; return(NULL); @@ -461,7 +459,7 @@ yp_get_record(const char *domain, const char *map, const DBT *key, if (ypdb_debug) yp_error("looking up key [%.*s]", - key->size, key->data); + (int)key->size, (char *)key->data); /* * Avoid passing back magic "YP_*" entries unless @@ -479,7 +477,7 @@ yp_get_record(const char *domain, const char *map, const DBT *key, if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #else dbp->close(dbp); #endif @@ -491,16 +489,17 @@ yp_get_record(const char *domain, const char *map, const DBT *key, if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", - key->size, key->data, data->size, data->data); + (int)key->size, (char *)key->data, + (int)data->size, (char *)data->data); #ifdef DB_CACHE - if (qhead.cqh_first->dbptr->size) { - qhead.cqh_first->dbptr->key = ""; - qhead.cqh_first->dbptr->size = 0; + if (TAILQ_FIRST(&qhead)->dbptr->size) { + TAILQ_FIRST(&qhead)->dbptr->key = ""; + TAILQ_FIRST(&qhead)->dbptr->size = 0; } #else - bcopy((char *)data->data, (char *)&buf, data->size); - data->data = (void *)&buf; + bcopy(data->data, &buf, data->size); + data->data = &buf; dbp->close(dbp); #endif @@ -520,7 +519,7 @@ yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif if (rval == 1) return(YP_NOKEY); @@ -532,7 +531,7 @@ yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) while (!strncmp(key->data, "YP_", 3) && !allow) { if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif if (rval == 1) return(YP_NOKEY); @@ -543,16 +542,17 @@ yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", - key->size, key->data, data->size, data->data); + (int)key->size, (char *)key->data, + (int)data->size, (char *)data->data); #ifdef DB_CACHE - if (qhead.cqh_first->dbptr->size) { - qhead.cqh_first->dbptr->key = key->data; - qhead.cqh_first->dbptr->size = key->size; + if (TAILQ_FIRST(&qhead)->dbptr->size) { + TAILQ_FIRST(&qhead)->dbptr->key = key->data; + TAILQ_FIRST(&qhead)->dbptr->size = key->size; } #else - bcopy((char *)data->data, (char *)&buf, data->size); - data->data = (void *)&buf; + bcopy(data->data, &buf, data->size); + data->data = &buf; #endif return(YP_TRUE); @@ -575,8 +575,8 @@ yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) return(YP_NOMORE); else { #ifdef DB_CACHE - qhead.cqh_first->dbptr->key = key->data; - qhead.cqh_first->dbptr->size = key->size; + TAILQ_FIRST(&qhead)->dbptr->key = key->data; + TAILQ_FIRST(&qhead)->dbptr->size = key->size; #endif return(rval); } @@ -584,19 +584,19 @@ yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) if (ypdb_debug) yp_error("retrieving next key, previous was: [%.*s]", - key->size, key->data); + (int)key->size, (char *)key->data); if (!all) { #ifdef DB_CACHE - if (qhead.cqh_first->dbptr->key == NULL) { + if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) { #endif (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); while (key->size != lkey.size || - strncmp((char *)key->data, lkey.data, + strncmp(key->data, lkey.data, (int)key->size)) if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOKEY); } @@ -608,7 +608,7 @@ yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) if ((dbp->seq)(dbp,key,data,R_NEXT)) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOMORE); } @@ -617,26 +617,27 @@ yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) while (!strncmp(key->data, "YP_", 3) && !allow) if ((dbp->seq)(dbp,key,data,R_NEXT)) { #ifdef DB_CACHE - qhead.cqh_first->dbptr->size = 0; + TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOMORE); } if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", - key->size, key->data, data->size, data->data); + (int)key->size, (char *)key->data, + (int)data->size, (char *)data->data); #ifdef DB_CACHE - if (qhead.cqh_first->dbptr->size) { - qhead.cqh_first->dbptr->key = key->data; - qhead.cqh_first->dbptr->size = key->size; + if (TAILQ_FIRST(&qhead)->dbptr->size) { + TAILQ_FIRST(&qhead)->dbptr->key = key->data; + TAILQ_FIRST(&qhead)->dbptr->size = key->size; } #else - bcopy((char *)key->data, (char *)&keybuf, key->size); - lkey.data = (void *)&keybuf; + bcopy(key->data, &keybuf, key->size); + lkey.data = &keybuf; lkey.size = key->size; - bcopy((char *)data->data, (char *)&datbuf, data->size); - data->data = (void *)&datbuf; + bcopy(data->data, &datbuf, data->size); + data->data = &datbuf; #endif return(YP_TRUE); diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c index cdeb639463..6c94479cb5 100644 --- a/usr.sbin/ypserv/yp_dnslookup.c +++ b/usr.sbin/ypserv/yp_dnslookup.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_dnslookup.c,v 1.16.2.1 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_dnslookup.c,v 1.27 2005/05/20 13:04:10 charnier Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_dnslookup.c,v 1.4 2005/11/24 22:23:02 swildner Exp $ */ @@ -68,13 +68,17 @@ static char * parse(struct hostent *hp) { static char result[MAXHOSTNAMELEN * 2]; - int len,i; - struct in_addr addr; + int i; + size_t len; + char addr[46]; if (hp == NULL) return(NULL); - len = 16 + strlen(hp->h_name); + if (inet_ntop(hp->h_addrtype, hp->h_addr, addr, sizeof(addr)) == NULL) + return(NULL); + + len = strlen(addr) + 1 + strlen(hp->h_name); for (i = 0; hp->h_aliases[i]; i++) len += strlen(hp->h_aliases[i]) + 1; len++; @@ -83,10 +87,7 @@ parse(struct hostent *hp) return(NULL); bzero(result, sizeof(result)); - - bcopy(hp->h_addr, &addr, sizeof(struct in_addr)); - snprintf(result, sizeof(result), "%s %s", inet_ntoa(addr), hp->h_name); - + snprintf(result, sizeof(result), "%s %s", addr, hp->h_name); for (i = 0; hp->h_aliases[i]; i++) { strcat(result, " "); strcat(result, hp->h_aliases[i]); @@ -95,7 +96,7 @@ parse(struct hostent *hp) return ((char *)&result); } -#define MAXPACKET 1024 +#define MAXPACKET (64*1024) #define DEF_TTL 50 #define BY_DNS_ID 1 @@ -103,7 +104,7 @@ parse(struct hostent *hp) extern struct hostent *__dns_getanswer(char *, int, char *, int); -static CIRCLEQ_HEAD(dns_qhead, circleq_dnsentry) qhead; +static TAILQ_HEAD(dns_qhead, circleq_dnsentry) qhead; struct circleq_dnsentry { SVCXPRT *xprt; @@ -116,8 +117,10 @@ struct circleq_dnsentry { unsigned short prot_type; char **domain; char *name; - struct in_addr addr; - CIRCLEQ_ENTRY(circleq_dnsentry) links; + int addrtype; + int addrlen; + uint32_t addr[4]; /* IPv4 or IPv6 */ + TAILQ_ENTRY(circleq_dnsentry) links; }; static int pending = 0; @@ -125,7 +128,7 @@ static int pending = 0; int yp_init_resolver(void) { - CIRCLEQ_INIT(&qhead); + TAILQ_INIT(&qhead); if (!(_res.options & RES_INIT) && res_init() == -1) { yp_error("res_init failed"); return(1); @@ -174,7 +177,7 @@ yp_send_dns_query(char *name, int type) n = res_mkquery(QUERY,name,C_IN,type,NULL,0,NULL,buf,sizeof(buf)); if (n <= 0) { - yp_error("res_mkquery failed"); + yp_error("res_mkquery failed for %s type %d", name, type); return(0); } @@ -199,7 +202,7 @@ yp_find_dnsqent(unsigned long id, int type) { struct circleq_dnsentry *q; - for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) { + TAILQ_FOREACH(q, &qhead, links) { switch (type) { case BY_RPC_XID: if (id == q->xid) @@ -251,8 +254,8 @@ yp_send_dns_reply(struct circleq_dnsentry *q, char *buf) */ bzero((char *)&result_v1, sizeof(result_v1)); result_v1.yp_resptype = YPRESP_VAL; -# define YPVAL ypresponse_u.yp_resp_valtype +#define YPVAL ypresponse_u.yp_resp_valtype if (buf == NULL) result_v1.YPVAL.stat = YP_NOKEY; else { @@ -316,12 +319,12 @@ yp_prune_dnsq(void) { struct circleq_dnsentry *q, *n; - q = qhead.cqh_first; - while (q != (void *)&qhead) { + q = TAILQ_FIRST(&qhead); + while (q != NULL) { q->ttl--; - n = q->links.cqe_next; + n = TAILQ_NEXT(q, links); if (!q->ttl) { - CIRCLEQ_REMOVE(&qhead, q, links); + TAILQ_REMOVE(&qhead, q, links); free(q->name); free(q); pending--; @@ -344,10 +347,9 @@ yp_run_dnsq(void) { struct circleq_dnsentry *q; char buf[sizeof(HEADER) + MAXPACKET]; - char retrybuf[MAXHOSTNAMELEN]; struct sockaddr_in sin; + socklen_t len; int rval; - int len; HEADER *hptr; struct hostent *hent; @@ -384,34 +386,18 @@ yp_run_dnsq(void) hent = __dns_getanswer(buf, rval, q->name, q->type); - /* - * If the lookup failed, try appending one of the domains - * from resolv.conf. If we have no domains to test, the - * query has failed. - */ - if (hent == NULL) { - if ((h_errno == TRY_AGAIN || h_errno == NO_RECOVERY) - && q->domain && *q->domain) { - snprintf(retrybuf, sizeof(retrybuf), "%s.%s", - q->name, *q->domain); - if (debug) - yp_error("retrying with: %s", retrybuf); - q->id = yp_send_dns_query(retrybuf, q->type); - q->ttl = DEF_TTL; - q->domain++; - return; - } - } else { + if (hent != NULL) { if (q->type == T_PTR) { - hent->h_addr = (char *)&q->addr.s_addr; - hent->h_length = sizeof(struct in_addr); + hent->h_addr = (char *)q->addr; + hent->h_addrtype = q->addrtype; + hent->h_length = q->addrlen; } } /* Got an answer ready for a client -- send it off. */ yp_send_dns_reply(q, parse(hent)); pending--; - CIRCLEQ_REMOVE(&qhead, q, links); + TAILQ_REMOVE(&qhead, q, links); free(q->name); free(q); @@ -425,14 +411,16 @@ yp_run_dnsq(void) * Queue and transmit an asynchronous DNS hostname lookup. */ ypstat -yp_async_lookup_name(struct svc_req *rqstp, char *name) +yp_async_lookup_name(struct svc_req *rqstp, char *name, int af) { struct circleq_dnsentry *q; - int type, len; + socklen_t len; + int type; /* 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, + type = -1; + len = sizeof(type); + if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET, SO_TYPE, &type, &len) == -1) { yp_error("getsockopt failed: %s", strerror(errno)); return(YP_YPERR); @@ -446,7 +434,7 @@ yp_async_lookup_name(struct svc_req *rqstp, char *name) if ((q = yp_malloc_dnsent()) == NULL) return(YP_YPERR); - q->type = T_A; + q->type = (af == AF_INET) ? T_A : T_AAAA; q->ttl = DEF_TTL; q->xprt = rqstp->rq_xprt; q->ypvers = rqstp->rq_vers; @@ -464,7 +452,7 @@ yp_async_lookup_name(struct svc_req *rqstp, char *name) } q->name = strdup(name); - CIRCLEQ_INSERT_HEAD(&qhead, q, links); + TAILQ_INSERT_HEAD(&qhead, q, links); pending++; if (debug) @@ -478,16 +466,19 @@ yp_async_lookup_name(struct svc_req *rqstp, char *name) * Queue and transmit an asynchronous DNS IP address lookup. */ ypstat -yp_async_lookup_addr(struct svc_req *rqstp, char *addr) +yp_async_lookup_addr(struct svc_req *rqstp, char *addr, int af) { struct circleq_dnsentry *q; - char buf[MAXHOSTNAMELEN]; - int a, b, c, d; - int type, len; + char buf[MAXHOSTNAMELEN], *qp; + uint32_t abuf[4]; /* IPv4 or IPv6 */ + u_char *uaddr = (u_char *)abuf; + socklen_t len; + int type, n; /* 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, + type = -1; + len = sizeof(type); + if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET, SO_TYPE, &type, &len) == -1) { yp_error("getsockopt failed: %s", strerror(errno)); return(YP_YPERR); @@ -501,10 +492,29 @@ yp_async_lookup_addr(struct svc_req *rqstp, char *addr) if ((q = yp_malloc_dnsent()) == NULL) return(YP_YPERR); - if (sscanf(addr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) - return(YP_NOKEY); - - snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", d, c, b, a); + switch (af) { + case AF_INET: + if (inet_aton(addr, (struct in_addr *)uaddr) != 1) + return(YP_NOKEY); + snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), (uaddr[2] & 0xff), + (uaddr[1] & 0xff), (uaddr[0] & 0xff)); + len = INADDRSZ; + break; + case AF_INET6: + if (inet_pton(af, addr, uaddr) != 1) + return(YP_NOKEY); + qp = buf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += (size_t)sprintf(qp, "%x.%x.", uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf); + } + strlcat(buf, "ip6.arpa", sizeof(buf)); + len = IN6ADDRSZ; + break; + default: + return(YP_YPERR); + } if (debug) yp_error("DNS address is: %s", buf); @@ -526,9 +536,11 @@ yp_async_lookup_addr(struct svc_req *rqstp, char *addr) return(YP_YPERR); } - inet_aton(addr, &q->addr); + memcpy(q->addr, uaddr, len); + q->addrlen = len; + q->addrtype = af; q->name = strdup(buf); - CIRCLEQ_INSERT_HEAD(&qhead, q, links); + TAILQ_INSERT_HEAD(&qhead, q, links); pending++; if (debug) diff --git a/usr.sbin/ypserv/yp_error.c b/usr.sbin/ypserv/yp_error.c index 9c93ae81f1..61b0d3916f 100644 --- a/usr.sbin/ypserv/yp_error.c +++ b/usr.sbin/ypserv/yp_error.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_error.c,v 1.7 1999/08/28 01:21:12 peter Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_error.c,v 1.10 2003/05/03 21:06:42 obrien Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_error.c,v 1.4 2004/03/31 23:20:22 cpressey Exp $ */ @@ -38,19 +38,20 @@ * stolen from /usr/libexec/mail.local via ypserv */ -#include #include +#include +#include #include +#include "yp_extern.h" int debug; extern int _rpcpmstart; extern char *progname; -#include +static void __verr(const char *fmt, va_list ap) __printflike(1, 0); -static -void +static void __verr(const char *fmt, va_list ap) { if (debug && !_rpcpmstart) { diff --git a/usr.sbin/ypserv/yp_extern.h b/usr.sbin/ypserv/yp_extern.h index 1aa71679be..9593b9b1ea 100644 --- a/usr.sbin/ypserv/yp_extern.h +++ b/usr.sbin/ypserv/yp_extern.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_extern.h,v 1.14.2.2 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_extern.h,v 1.17 2005/05/02 09:34:07 ume Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_extern.h,v 1.2 2003/06/17 04:30:04 dillon Exp $ */ @@ -112,5 +112,5 @@ extern unsigned long svcudp_get_xid(SVCXPRT *); extern int yp_init_resolver(void); extern void yp_run_dnsq(void); extern void yp_prune_dnsq(void); -extern ypstat yp_async_lookup_name(struct svc_req *, char *); -extern ypstat yp_async_lookup_addr(struct svc_req *, char *); +extern ypstat yp_async_lookup_name(struct svc_req *, char *, int); +extern ypstat yp_async_lookup_addr(struct svc_req *, char *, int); diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c index a2ae8a24fd..8978f87d32 100644 --- a/usr.sbin/ypserv/yp_main.c +++ b/usr.sbin/ypserv/yp_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_main.c,v 1.21.2.3 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_main.c,v 1.29 2008/02/03 17:39:37 matteo Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_main.c,v 1.5 2005/11/24 22:23:02 swildner Exp $ */ @@ -84,6 +84,16 @@ char *yp_dir = _PATH_YP; int do_dns = 0; int resfd; +struct socktype { + const char *st_name; + int st_type; +}; +static struct socktype stlist[] = { + { "tcp", SOCK_STREAM }, + { "udp", SOCK_DGRAM }, + { NULL, 0 } +}; + static void _msgout(char *msg) { @@ -106,7 +116,6 @@ yp_svc_run(void) #else int readfds; #endif /* def FD_SETSIZE */ - extern int forked; int fd_setsize = _rpc_dtablesize(); struct timeval timeout; @@ -188,7 +197,7 @@ reaper(int sig) static void usage(void) { - fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path]\n"); + fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path] [-P port]\n"); exit(1); } @@ -229,10 +238,13 @@ main(int argc, char **argv) int sock; int proto = 0; struct sockaddr_in saddr; - int asize = sizeof(saddr); + socklen_t asize = sizeof (saddr); int ch; + in_port_t yp_port = 0; + char *errstr; + struct socktype *st; - while ((ch = getopt(argc, argv, "hdnp:")) != -1) { + while ((ch = getopt(argc, argv, "hdnp:P:")) != -1) { switch (ch) { case 'd': debug = ypdb_debug = 1; @@ -243,6 +255,14 @@ main(int argc, char **argv) case 'p': yp_dir = optarg; break; + case 'P': + yp_port = (in_port_t)strtonum(optarg, 1, 65535, + (const char **)&errstr); + if (yp_port == 0 && errstr != NULL) { + _msgout("invalid port number provided"); + exit(1); + } + break; case 'h': default: usage(); @@ -278,6 +298,39 @@ main(int argc, char **argv) pmap_unset(YPPROG, 1); } + /* + * Initialize TCP/UDP sockets. + */ + memset((char *)&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(yp_port); + for (st = stlist; st->st_name != NULL; st++) { + /* Do not bind the socket if the user didn't specify a port */ + if (yp_port == 0) + break; + + sock = socket(AF_INET, st->st_type, 0); + if (sock == -1) { + if ((asprintf(&errstr, "cannot create a %s socket", + st->st_name)) == -1) + err(1, "unexpected failure in asprintf()"); + _msgout(errstr); + free((void *)errstr); + exit(1); + } + if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)) + == -1) { + if ((asprintf(&errstr, "cannot bind %s socket", + st->st_name)) == -1) + err(1, "unexpected failure in asprintf()"); + _msgout(errstr); + free((void *)errstr); + exit(1); + } + errstr = NULL; + } + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { transp = svcudp_create(sock); if (transp == NULL) { diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c index 56ceac6a3f..68b0618302 100644 --- a/usr.sbin/ypserv/yp_server.c +++ b/usr.sbin/ypserv/yp_server.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_server.c,v 1.31.2.1 2002/02/15 00:47:00 des Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_server.c,v 1.40 2006/06/09 14:01:07 maxim Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_server.c,v 1.4 2005/11/24 22:23:02 swildner Exp $ */ @@ -163,11 +163,12 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) */ #ifdef DB_CACHE - if (result.stat != YP_TRUE && + if (do_dns && result.stat != YP_TRUE && (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || - (strstr(argp->map, "hosts") && do_dns))) { + (strstr(argp->map, "hosts") || strstr(argp->map, "ipnodes")))) { #else - if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { + if (do_dns && result.stat != YP_TRUE && + (strstr(argp->map, "hosts") || strstr(argp->map, "ipnodes"))) { #endif char nbuf[YPMAXRECORD]; @@ -179,9 +180,17 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) yp_error("doing DNS lookup of %s", nbuf); if (!strcmp(argp->map, "hosts.byname")) - result.stat = yp_async_lookup_name(rqstp, nbuf); + result.stat = yp_async_lookup_name(rqstp, nbuf, + AF_INET); else if (!strcmp(argp->map, "hosts.byaddr")) - result.stat = yp_async_lookup_addr(rqstp, nbuf); + result.stat = yp_async_lookup_addr(rqstp, nbuf, + AF_INET); + else if (!strcmp(argp->map, "ipnodes.byname")) + result.stat = yp_async_lookup_name(rqstp, nbuf, + AF_INET6); + else if (!strcmp(argp->map, "ipnodes.byaddr")) + result.stat = yp_async_lookup_addr(rqstp, nbuf, + AF_INET6); if (result.stat == YP_TRUE) return(NULL); @@ -282,7 +291,7 @@ ypxfr_callback(ypxfrstat rval, struct sockaddr_in *addr, unsigned int transid, /* Turn the timeout off -- we don't want to block. */ timeout.tv_sec = 0; - if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) + if (clnt_control(clnt, CLSET_TIMEOUT, &timeout) == FALSE) yp_error("failed to set timeout on ypproc_xfr callback"); if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { @@ -300,7 +309,7 @@ ypxfr_callback(ypxfrstat rval, struct sockaddr_in *addr, unsigned int transid, #define YPXFR_RETURN(CODE) \ /* Order is important: send regular RPC reply, then callback */ \ result.xfrstat = CODE; \ - svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ + svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_ypresp_xfr, &result); \ ypxfr_callback(CODE,rqhost,argp->transid, \ argp->prog,argp->port); \ return(NULL); @@ -361,10 +370,10 @@ ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) char g[11], t[11], p[11]; char ypxfr_command[MAXPATHLEN + 2]; - sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); - sprintf (t, "%u", argp->transid); - sprintf (g, "%u", argp->prog); - sprintf (p, "%u", argp->port); + snprintf (ypxfr_command, sizeof(ypxfr_command), "%sypxfr", _PATH_LIBEXEC); + snprintf (t, sizeof(t), "%u", argp->transid); + snprintf (g, sizeof(g), "%u", argp->prog); + snprintf (p, sizeof(p), "%u", argp->port); if (debug) { close(0); close(1); close(2); } @@ -547,7 +556,7 @@ ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) } /* Kick off the actual data transfer. */ - svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); + svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_my_ypresp_all, &result); /* * Proper fix for PR #10970: exit here so that we don't risk @@ -595,10 +604,9 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) */ result.stat = yp_getbykey(&key, &val); if (result.stat == YP_TRUE) { - bcopy((char *)val.valdat_val, (char *)&ypvalbuf, - val.valdat_len); + bcopy(val.valdat_val, &ypvalbuf, val.valdat_len); ypvalbuf[val.valdat_len] = '\0'; - result.peer = (char *)&ypvalbuf; + result.peer = ypvalbuf; } else result.peer = ""; @@ -643,7 +651,7 @@ ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) result.stat = yp_getbykey(&key, &val); if (result.stat == YP_TRUE) - result.ordernum = atoi((char *)val.valdat_val); + result.ordernum = atoi(val.valdat_val); else result.ordernum = 0; @@ -696,7 +704,7 @@ yp_maplist_create(const char *domain) yp_maplist_free(yp_maplist); return(NULL); } - if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { + if ((cur->map = strdup(dirp->d_name)) == NULL) { yp_error("strdup() failed: %s",strerror(errno)); closedir(dird); yp_maplist_free(yp_maplist); @@ -816,8 +824,7 @@ ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) if (v2_result == NULL) return(NULL); - bcopy((char *)v2_result, - (char *)&result.ypresponse_u.yp_resp_valtype, + bcopy(v2_result, &result.ypresponse_u.yp_resp_valtype, sizeof(ypresp_val)); return (&result); @@ -848,8 +855,7 @@ ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) if (v2_result == NULL) return(NULL); - bcopy((char *)v2_result, - (char *)&result.ypresponse_u.yp_resp_key_valtype, + bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, sizeof(ypresp_key_val)); return (&result); @@ -879,8 +885,7 @@ ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) if (v2_result == NULL) return(NULL); - bcopy((char *)v2_result, - (char *)&result.ypresponse_u.yp_resp_key_valtype, + bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, sizeof(ypresp_key_val)); return (&result); diff --git a/usr.sbin/ypserv/yp_svc_udp.c b/usr.sbin/ypserv/yp_svc_udp.c index 72cdc345ce..96d896139e 100644 --- a/usr.sbin/ypserv/yp_svc_udp.c +++ b/usr.sbin/ypserv/yp_svc_udp.c @@ -29,28 +29,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/ypserv/yp_svc_udp.c,v 1.5 1999/08/28 01:21:14 peter Exp $ + * $FreeBSD: src/usr.sbin/ypserv/yp_svc_udp.c,v 1.8 2003/05/03 21:06:42 obrien Exp $ * $DragonFly: src/usr.sbin/ypserv/yp_svc_udp.c,v 1.3 2004/03/31 23:20:22 cpressey Exp $ */ #include +#include #include "yp_extern.h" -/* - * XXX Must not diverge from what's in src/lib/libc/rpc/svc_udp.c - */ - -/* - * 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)) +#define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2)) /* * We need to be able to manually set the transaction ID in the @@ -61,7 +48,7 @@ struct svcudp_data { unsigned long svcudp_get_xid(SVCXPRT *xprt) { - struct svcudp_data *su; + struct svc_dg_data *su; if (xprt == NULL) return(0); @@ -72,7 +59,7 @@ svcudp_get_xid(SVCXPRT *xprt) unsigned long svcudp_set_xid(SVCXPRT *xprt, unsigned long xid) { - struct svcudp_data *su; + struct svc_dg_data *su; unsigned long old_xid; if (xprt == NULL) diff --git a/usr.sbin/ypserv/ypinit.8 b/usr.sbin/ypserv/ypinit.8 index 1abef6483c..19a6cf863b 100644 --- a/usr.sbin/ypserv/ypinit.8 +++ b/usr.sbin/ypserv/ypinit.8 @@ -28,7 +28,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF .\" THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/ypserv/ypinit.8,v 1.7.2.6 2003/03/11 22:31:35 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/ypserv/ypinit.8,v 1.17 2006/06/08 14:49:38 maxim Exp $ .\" $DragonFly: src/usr.sbin/ypserv/ypinit.8,v 1.3 2007/05/13 22:25:42 swildner Exp $ .\" .Dd November 10, 1997 @@ -162,6 +162,8 @@ Protocols source file RPC public key/secret key source file .It Pa /etc/services Services data source file +.It Pa /etc/shells +Shells source file .It Pa /var/yp/master.passwd Passwd database source file .It Pa /var/yp/netgroup @@ -174,10 +176,10 @@ Ypservers source file (generated by .Xr mknetid 8 , .Xr revnetgroup 8 , .Xr yp 8 , +.Xr yp_mkdb 8 , .Xr yppush 8 , .Xr ypserv 8 , -.Xr ypxfr 8 , -.Xr yp_mkdb 8 +.Xr ypxfr 8 .Sh HISTORY This version of .Nm diff --git a/usr.sbin/ypserv/ypinit.sh b/usr.sbin/ypserv/ypinit.sh index a2a2d86720..c96065afa8 100644 --- a/usr.sbin/ypserv/ypinit.sh +++ b/usr.sbin/ypserv/ypinit.sh @@ -1,8 +1,8 @@ #!/bin/sh -# $FreeBSD: src/usr.sbin/ypserv/ypinit.sh,v 1.3 1999/08/28 01:21:15 peter Exp $ +# $FreeBSD: src/usr.sbin/ypserv/ypinit.sh,v 1.4 2002/12/30 21:18:15 schweikh Exp $ # $DragonFly: src/usr.sbin/ypserv/ypinit.sh,v 1.3 2007/05/13 22:25:42 swildner Exp $ # -# ypinit.sh - setup an master or slave server. +# ypinit.sh - setup a master or slave server. # (Taken from OpenBSD and modified for FreeBSD.) # DOMAINNAME=/bin/domainname @@ -181,7 +181,7 @@ __notice1 esac if [ -d "${YP_DIR}/${DOMAIN}" ]; then - echo "" + echo "" echo -n "Can we destroy the existing ${YP_DIR}/${DOMAIN} and its contents? [y/n: n] " read KILL @@ -204,7 +204,6 @@ __notice1 echo "OK, please clean it up by hand and start again. Bye" exit 0 fi - fi if ! mkdir "${YP_DIR}/${DOMAIN}"; then @@ -262,7 +261,6 @@ LIST_OK="NO" while [ "${LIST_OK}" = "NO" ]; do - if [ "${SERVERTYPE}" = "MASTER" ]; then HOST_LIST="${HOST}" @@ -301,8 +299,8 @@ do echo "Update the list of hosts running YP servers in domain ${DOMAIN}." echo "Master for this domain is ${MASTER_NAME}." echo "" - echo "First verify old servers, type \\ to remove a server." - echo "Then add new servers, one per line. When done type a ." + echo "First verify old servers, type \\ to remove a server." + echo "Then add new servers, one per line. When done type a ." echo "" echo " master server : ${HOST}" if [ "${NEW_LIST}" != "" ]; then @@ -359,13 +357,12 @@ if [ $? -ne 0 ]; then echo "" 1>&2 echo "Couldn't build yp data base ${YP_DIR}/${DOMAIN}/ypservers." 1>&2 ERROR_EXISTS="YES" - if [ "${ERROR_EXIT}" = "YES" ]; then + if [ "${ERROR_EXIT}" = "YES" ]; then exit 1 fi fi if [ "${SERVERTYPE}" = "MASTER" ]; then - CUR_PWD=`pwd` cd ${YP_DIR} echo "Running ${YP_DIR}/Makefile..." @@ -373,7 +370,7 @@ if [ "${SERVERTYPE}" = "MASTER" ]; then echo "" 1>&2 echo "Error running Makefile." 1>&2 ERROR_EXISTS="YES" - if [ "${ERROR_EXIT}" = "YES" ]; then + if [ "${ERROR_EXIT}" = "YES" ]; then exit 1 fi fi @@ -387,5 +384,4 @@ if [ "${SERVERTYPE}" = "MASTER" ]; then else echo "${HOST} has been setup as an YP master server without any errors. " fi - fi diff --git a/usr.sbin/ypserv/ypserv.8 b/usr.sbin/ypserv/ypserv.8 index e5e498e969..2bd476dae2 100644 --- a/usr.sbin/ypserv/ypserv.8 +++ b/usr.sbin/ypserv/ypserv.8 @@ -28,10 +28,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.sbin/ypserv/ypserv.8,v 1.22.2.8 2002/12/29 16:35:44 schweikh Exp $ +.\" $FreeBSD: src/usr.sbin/ypserv/ypserv.8,v 1.42 2008/02/03 17:39:37 matteo Exp $ .\" $DragonFly: src/usr.sbin/ypserv/ypserv.8,v 1.8 2007/12/16 02:55:38 thomas Exp $ .\" -.Dd February 4, 1995 +.Dd February 3, 2008 .Dt YPSERV 8 .Os .Sh NAME @@ -41,6 +41,7 @@ .Nm .Op Fl n .Op Fl d +.Op Fl P Ar port .Op Fl p Ar path .Sh DESCRIPTION .Tn NIS @@ -61,7 +62,7 @@ updated from a single location. .Pp The .Nm -program is the server that distributes +utility is the server that distributes .Tn NIS databases to client systems within an .Tn NIS @@ -108,21 +109,21 @@ the maps are always readable and writable only by root for security reasons. Technically this is only necessary for the password maps, but since the data in the other maps can be found in -other world-readable files anyway, it doesn't hurt and it's considered +other world-readable files anyway, it does not hurt and it is considered good general practice. .Pp The .Nm -program is started at boot time by setting the -.Va yp_server_enable -variable in +utility is started by +.Pa /etc/rc.d/ypserv +if it has been enabled in .Pa /etc/rc.conf . .Sh SPECIAL FEATURES There are some problems associated with distributing a .Dx password database via -.Tn NIS Ns : +.Tn NIS : .Dx normally only stores encrypted passwords in @@ -274,20 +275,9 @@ will allow connections from any host. .Pp The .Nm -program also has support for Wietse Venema's +utility also has support for Wietse Venema's .Em tcpwrapper -package, though it is not compiled in by default since -the -.Em tcpwrapper -package is not distributed with -.Dx . -However, if you have -.Pa libwrap.a -and -.In tcpd.h , -you can easily recompile -.Nm -with them. +package. This allows the administrator to use the tcpwrapper configuration files .Pa ( /etc/hosts.allow @@ -322,7 +312,8 @@ to an .Tn NIS v1 server even though they may never actually need it (and they may persist in broadcasting in search of one even after they receive a -response from a v2 server). Note that while +response from a v2 server). +Note that while support for normal client calls is provided, this version of .Nm does not handle v1 map transfer requests; consequently, it cannot @@ -330,7 +321,7 @@ be used as a master or slave in conjunction with older .Tn NIS servers that only support the v1 protocol. -Fortunately, there probably aren't any +Fortunately, there probably are not any such servers still in use today. .Ss NIS servers that are also NIS clients Care must be taken when running @@ -366,7 +357,7 @@ and maps. By default, if .Nm -can't find an entry for a given host in its hosts maps, it will +cannot find an entry for a given host in its hosts maps, it will return an error and perform no further processing. With the .Fl n @@ -415,6 +406,9 @@ in subprocesses, allowing the parent server process to go on handling other requests.) This makes it easier to trace the server with a debugging tool. +.It Fl P Ar port +Force ypserv to bind to a specific TCP/UDP port, rather than selecting +its own. .It Fl p Ar path Normally, .Nm @@ -428,7 +422,7 @@ flag may be used to specify an alternate .Tn NIS root path, allowing the system administrator to move the map files to a different place -within the filesystem. +within the file system. .El .Sh FILES .Bl -tag -width Pa -compact @@ -444,6 +438,7 @@ host access control file .Sh SEE ALSO .Xr ypcat 1 , .Xr db 3 , +.Xr hosts_access 5 , .Xr rc.conf 5 , .Xr rpc.yppasswdd 8 , .Xr tcpd 8 , -- 2.41.0