From df49c60c9671e4a28e636964d744c1f59fb6cb68 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 12 Jun 2000 15:00:15 +0000 Subject: Merged from 4.5.0-beta3a --- c/src/exec/itron/include/Makefile.am | 9 +- c/src/exec/itron/include/itronsys/Makefile.am | 13 +- c/src/exec/itron/include/rtems/itron/Makefile.am | 13 +- c/src/exec/itron/inline/rtems/itron/Makefile.am | 14 +- c/src/exec/itron/src/Makefile.am | 25 +- c/src/exec/itron/src/cre_tsk.c | 3 +- c/src/exec/itron/src/eventflags.c | 2 +- c/src/exec/itron/src/fmempool.c | 2 +- c/src/exec/itron/src/itronsem.c | 2 +- c/src/exec/itron/src/mbox.c | 2 +- c/src/exec/itron/src/msgbuffer.c | 2 +- c/src/exec/itron/src/port.c | 2 +- c/src/exec/itron/src/vmempool.c | 2 +- c/src/exec/libcsupport/Makefile.am | 3 +- c/src/exec/libcsupport/include/console.h | 4 - c/src/exec/libcsupport/include/rtems/error.h | 9 + c/src/exec/libcsupport/include/sys/termios.h | 10 +- c/src/exec/libcsupport/src/Makefile.am | 33 +- c/src/exec/libcsupport/src/gxx_wrappers.c | 219 ++ c/src/exec/libcsupport/src/libio.c | 4 +- c/src/exec/libcsupport/src/malloc.c | 2 +- c/src/exec/libcsupport/src/scandir.c | 2 +- c/src/exec/libcsupport/src/termios.c | 15 +- .../exec/libcsupport/src/termiosreserveresources.c | 5 + c/src/exec/libcsupport/src/unmount.c | 12 +- c/src/exec/libfs/src/imfs/imfs.h | 16 +- c/src/exec/libfs/src/imfs/imfs_creat.c | 6 +- c/src/exec/libfs/src/imfs/imfs_directory.c | 12 +- c/src/exec/libfs/src/imfs/imfs_stat.c | 6 +- c/src/exec/libfs/src/imfs/imfs_utime.c | 4 +- c/src/exec/libnetworking/Makefile.am | 6 +- c/src/exec/libnetworking/arpa/Makefile.am | 14 +- c/src/exec/libnetworking/kern/Makefile.am | 4 +- c/src/exec/libnetworking/lib/Makefile.am | 4 +- c/src/exec/libnetworking/lib/rtems_bsdnet_ntp.c | 6 +- c/src/exec/libnetworking/libc/Makefile.am | 26 +- c/src/exec/libnetworking/machine/Makefile.am | 19 +- c/src/exec/libnetworking/memory.h | 5 + c/src/exec/libnetworking/net/Makefile.am | 24 +- c/src/exec/libnetworking/net/if_loop.c | 1 + c/src/exec/libnetworking/netinet/Makefile.am | 34 +- c/src/exec/libnetworking/netinet/in.h | 3 + c/src/exec/libnetworking/nfs/Makefile.am | 22 +- c/src/exec/libnetworking/rtems/Makefile.am | 25 +- c/src/exec/libnetworking/rtems/rtems_syscall.c | 17 +- c/src/exec/libnetworking/sys/Makefile.am | 16 +- c/src/exec/libnetworking/sys/un.h | 68 + c/src/exec/libnetworking/vm/Makefile.am | 19 +- c/src/exec/libnetworking/wrapup/Makefile.am | 6 +- c/src/exec/librpc/Makefile.am | 2 + c/src/exec/librpc/README_RTEMS | 64 + c/src/exec/librpc/include/Makefile.am | 2 +- c/src/exec/librpc/include/rpc/Makefile.am | 13 +- c/src/exec/librpc/include/rpc/auth.h | 143 +- c/src/exec/librpc/include/rpc/auth_des.h | 109 + c/src/exec/librpc/include/rpc/auth_unix.h | 84 + c/src/exec/librpc/include/rpc/clnt.h | 205 +- c/src/exec/librpc/include/rpc/des.h | 82 + c/src/exec/librpc/include/rpc/des_crypt.h | 120 + c/src/exec/librpc/include/rpc/pmap_clnt.h | 85 + c/src/exec/librpc/include/rpc/pmap_prot.h | 104 + c/src/exec/librpc/include/rpc/pmap_rmt.h | 63 + c/src/exec/librpc/include/rpc/rpc.h | 83 +- c/src/exec/librpc/include/rpc/rpc_com.h | 78 + c/src/exec/librpc/include/rpc/rpc_msg.h | 56 +- c/src/exec/librpc/include/rpc/svc.h | 153 +- c/src/exec/librpc/include/rpc/svc_auth.h | 37 +- c/src/exec/librpc/include/rpc/types.h | 51 +- c/src/exec/librpc/include/rpc/xdr.h | 175 +- c/src/exec/librpc/include/rpcsvc/.cvsignore | 2 + c/src/exec/librpc/include/rpcsvc/Makefile.am | 13 + c/src/exec/librpc/include/rpcsvc/bootparam_prot.x | 103 + c/src/exec/librpc/include/rpcsvc/crypt.x | 91 + c/src/exec/librpc/include/rpcsvc/key_prot.x | 284 +++ c/src/exec/librpc/include/rpcsvc/klm_prot.x | 139 + c/src/exec/librpc/include/rpcsvc/mount.x | 257 ++ c/src/exec/librpc/include/rpcsvc/nfs_prot.x | 1266 +++++++++ c/src/exec/librpc/include/rpcsvc/nis.x | 466 ++++ c/src/exec/librpc/include/rpcsvc/nis_cache.x | 87 + c/src/exec/librpc/include/rpcsvc/nis_callback.x | 76 + c/src/exec/librpc/include/rpcsvc/nis_db.h | 162 ++ c/src/exec/librpc/include/rpcsvc/nis_object.x | 317 +++ c/src/exec/librpc/include/rpcsvc/nis_tags.h | 137 + c/src/exec/librpc/include/rpcsvc/nislib.h | 317 +++ c/src/exec/librpc/include/rpcsvc/nlm_prot.x | 184 ++ c/src/exec/librpc/include/rpcsvc/pmap_prot.x | 285 +++ c/src/exec/librpc/include/rpcsvc/rex.x | 235 ++ c/src/exec/librpc/include/rpcsvc/rnusers.x | 123 + c/src/exec/librpc/include/rpcsvc/rquota.x | 67 + c/src/exec/librpc/include/rpcsvc/rstat.x | 151 ++ c/src/exec/librpc/include/rpcsvc/rwall.x | 57 + c/src/exec/librpc/include/rpcsvc/sm_inter.x | 122 + c/src/exec/librpc/include/rpcsvc/spray.x | 90 + c/src/exec/librpc/include/rpcsvc/yp.x | 379 +++ c/src/exec/librpc/include/rpcsvc/yp_prot.h | 329 +++ c/src/exec/librpc/include/rpcsvc/ypclnt.h | 94 + c/src/exec/librpc/include/rpcsvc/yppasswd.x | 75 + c/src/exec/librpc/include/rpcsvc/ypupdate_prot.x | 88 + c/src/exec/librpc/include/rpcsvc/ypxfrd.x | 173 ++ c/src/exec/librpc/src/Makefile.am | 31 +- c/src/exec/librpc/src/rpc/DISCLAIMER | 28 + c/src/exec/librpc/src/rpc/Makefile.am | 57 + c/src/exec/librpc/src/rpc/PSD.doc/.cvsignore | 2 + c/src/exec/librpc/src/rpc/PSD.doc/Makefile.am | 8 + c/src/exec/librpc/src/rpc/PSD.doc/nfs.rfc.ms | 1372 ++++++++++ c/src/exec/librpc/src/rpc/PSD.doc/rpc.prog.ms | 2684 ++++++++++++++++++++ c/src/exec/librpc/src/rpc/PSD.doc/rpc.rfc.ms | 1302 ++++++++++ c/src/exec/librpc/src/rpc/PSD.doc/rpcgen.ms | 1299 ++++++++++ c/src/exec/librpc/src/rpc/PSD.doc/xdr.nts.ms | 1966 ++++++++++++++ c/src/exec/librpc/src/rpc/PSD.doc/xdr.rfc.ms | 1058 ++++++++ c/src/exec/librpc/src/rpc/README | 233 ++ c/src/exec/librpc/src/rpc/auth_des.c | 554 ++++ c/src/exec/librpc/src/rpc/auth_none.c | 136 + c/src/exec/librpc/src/rpc/auth_time.c | 503 ++++ c/src/exec/librpc/src/rpc/auth_unix.c | 349 +++ c/src/exec/librpc/src/rpc/authdes_prot.c | 82 + c/src/exec/librpc/src/rpc/authunix_prot.c | 68 + c/src/exec/librpc/src/rpc/bindresvport.3 | 106 + c/src/exec/librpc/src/rpc/bindresvport.c | 147 ++ c/src/exec/librpc/src/rpc/clnt_generic.c | 141 + c/src/exec/librpc/src/rpc/clnt_perror.c | 254 ++ c/src/exec/librpc/src/rpc/clnt_raw.c | 243 ++ c/src/exec/librpc/src/rpc/clnt_simple.c | 123 + c/src/exec/librpc/src/rpc/clnt_tcp.c | 580 +++++ c/src/exec/librpc/src/rpc/clnt_udp.c | 567 +++++ c/src/exec/librpc/src/rpc/clnt_unix.c | 635 +++++ c/src/exec/librpc/src/rpc/crypt_client.c | 90 + c/src/exec/librpc/src/rpc/des_crypt.3 | 130 + c/src/exec/librpc/src/rpc/des_crypt.c | 153 ++ c/src/exec/librpc/src/rpc/des_soft.c | 67 + c/src/exec/librpc/src/rpc/get_myaddress.c | 112 + c/src/exec/librpc/src/rpc/getpublickey.c | 172 ++ c/src/exec/librpc/src/rpc/getrpcent.3 | 98 + c/src/exec/librpc/src/rpc/getrpcent.c | 303 +++ c/src/exec/librpc/src/rpc/getrpcport.3 | 31 + c/src/exec/librpc/src/rpc/getrpcport.c | 63 + c/src/exec/librpc/src/rpc/key_call.c | 427 ++++ c/src/exec/librpc/src/rpc/key_prot_xdr.c | 166 ++ c/src/exec/librpc/src/rpc/netname.c | 136 + c/src/exec/librpc/src/rpc/netnamer.c | 326 +++ c/src/exec/librpc/src/rpc/pmap_clnt.c | 149 ++ c/src/exec/librpc/src/rpc/pmap_getmaps.c | 86 + c/src/exec/librpc/src/rpc/pmap_getport.c | 91 + c/src/exec/librpc/src/rpc/pmap_prot.c | 59 + c/src/exec/librpc/src/rpc/pmap_prot2.c | 118 + c/src/exec/librpc/src/rpc/pmap_rmt.c | 415 +++ c/src/exec/librpc/src/rpc/publickey.3 | 47 + c/src/exec/librpc/src/rpc/publickey.5 | 38 + c/src/exec/librpc/src/rpc/rpc.3 | 1767 +++++++++++++ c/src/exec/librpc/src/rpc/rpc.5 | 35 + c/src/exec/librpc/src/rpc/rpc_callmsg.c | 193 ++ c/src/exec/librpc/src/rpc/rpc_commondata.c | 41 + c/src/exec/librpc/src/rpc/rpc_dtablesize.c | 61 + c/src/exec/librpc/src/rpc/rpc_prot.c | 297 +++ c/src/exec/librpc/src/rpc/rpc_secure.3 | 254 ++ c/src/exec/librpc/src/rpc/rpcdname.c | 78 + c/src/exec/librpc/src/rpc/rstat.1 | 58 + c/src/exec/librpc/src/rpc/rstat_svc.8 | 22 + c/src/exec/librpc/src/rpc/rtems_portmapper.c | 488 ++++ c/src/exec/librpc/src/rpc/rtems_rpc.c | 56 + c/src/exec/librpc/src/rpc/rtime.3 | 47 + c/src/exec/librpc/src/rpc/rtime.c | 157 ++ c/src/exec/librpc/src/rpc/svc.c | 491 ++++ c/src/exec/librpc/src/rpc/svc_auth.c | 216 ++ c/src/exec/librpc/src/rpc/svc_auth_des.c | 531 ++++ c/src/exec/librpc/src/rpc/svc_auth_unix.c | 148 ++ c/src/exec/librpc/src/rpc/svc_raw.c | 169 ++ c/src/exec/librpc/src/rpc/svc_run.c | 83 + c/src/exec/librpc/src/rpc/svc_simple.c | 151 ++ c/src/exec/librpc/src/rpc/svc_tcp.c | 481 ++++ c/src/exec/librpc/src/rpc/svc_udp.c | 480 ++++ c/src/exec/librpc/src/rpc/svc_unix.c | 527 ++++ c/src/exec/librpc/src/xdr/Makefile.am | 44 + c/src/exec/librpc/src/xdr/xdr.3 | 837 ++++++ c/src/exec/librpc/src/xdr/xdr.c | 777 ++++++ c/src/exec/librpc/src/xdr/xdr_array.c | 157 ++ c/src/exec/librpc/src/xdr/xdr_float.c | 331 +++ c/src/exec/librpc/src/xdr/xdr_mem.c | 242 ++ c/src/exec/librpc/src/xdr/xdr_rec.c | 601 +++++ c/src/exec/librpc/src/xdr/xdr_reference.c | 138 + c/src/exec/librpc/src/xdr/xdr_sizeof.c | 163 ++ c/src/exec/librpc/src/xdr/xdr_stdio.c | 189 ++ c/src/exec/posix/include/Makefile.am | 13 +- c/src/exec/posix/include/pthread.h | 509 ---- c/src/exec/posix/include/rtems/posix/Makefile.am | 11 +- c/src/exec/posix/include/sys/Makefile.am | 9 +- c/src/exec/posix/inline/rtems/posix/Makefile.am | 12 +- c/src/exec/posix/inline/rtems/posix/cond.inl | 9 +- c/src/exec/posix/macros/rtems/posix/Makefile.am | 9 +- c/src/exec/posix/optman/Makefile.am | 3 +- c/src/exec/posix/src/Makefile.am | 5 +- c/src/exec/posix/src/mqueuecreatesupp.c | 8 +- c/src/exec/posix/src/mqueuedeletesupp.c | 2 +- c/src/exec/posix/src/mqueueunlink.c | 2 +- c/src/exec/posix/src/pthread.c | 4 +- c/src/exec/posix/src/pthreadcreate.c | 3 +- c/src/exec/posix/src/sigtimedwait.c | 42 +- c/src/exec/posix/src/waitpid.c | 6 +- c/src/exec/rtems/include/Makefile.am | 9 +- c/src/exec/rtems/include/rtems/rtems/Makefile.am | 19 +- c/src/exec/rtems/include/rtems/rtems/rtemsapi.h | 4 +- c/src/exec/rtems/inline/rtems/rtems/Makefile.am | 13 +- c/src/exec/rtems/macros/rtems/rtems/Makefile.am | 13 +- c/src/exec/rtems/optman/Makefile.am | 3 +- c/src/exec/rtems/optman/no-mp.c | 1 + c/src/exec/rtems/src/Makefile.am | 5 +- c/src/exec/rtems/src/semdelete.c | 37 +- c/src/exec/rtems/src/tasks.c | 8 +- c/src/exec/rtems/src/taskvariableadd.c | 2 +- c/src/exec/rtems/src/taskvariabledelete.c | 2 + c/src/exec/rtems/src/taskvariableget.c | 2 +- c/src/exec/sapi/include/Makefile.am | 9 +- c/src/exec/sapi/include/confdefs.h | 178 +- c/src/exec/sapi/include/rtems/Makefile.am | 11 +- c/src/exec/sapi/include/rtems/README | 16 +- c/src/exec/sapi/inline/rtems/Makefile.am | 9 +- c/src/exec/sapi/macros/rtems/Makefile.am | 9 +- c/src/exec/sapi/optman/Makefile.am | 3 +- c/src/exec/sapi/src/Makefile.am | 3 +- c/src/exec/score/cpu/a29k/Makefile.am | 7 +- c/src/exec/score/cpu/a29k/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/a29k/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/a29k/rtems/score/a29k.h | 11 +- c/src/exec/score/cpu/hppa1.1/Makefile.am | 7 +- c/src/exec/score/cpu/hppa1.1/rtems/Makefile.am | 4 +- .../exec/score/cpu/hppa1.1/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/hppa1.1/rtems/score/hppa.h | 10 +- c/src/exec/score/cpu/i386/Makefile.am | 7 +- c/src/exec/score/cpu/i386/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/i386/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/i386/rtems/score/i386.h | 12 +- c/src/exec/score/cpu/i960/Makefile.am | 7 +- c/src/exec/score/cpu/i960/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/i960/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/i960/rtems/score/i960.h | 13 +- c/src/exec/score/cpu/m68k/Makefile.am | 7 +- c/src/exec/score/cpu/m68k/qsm.h | 4 - c/src/exec/score/cpu/m68k/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/m68k/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/m68k/rtems/score/m68k.h | 9 + c/src/exec/score/cpu/m68k/sim.h | 7 - c/src/exec/score/cpu/mips/Makefile.am | 7 +- c/src/exec/score/cpu/mips/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/mips/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/mips/rtems/score/mips.h | 11 +- .../exec/score/cpu/mips/rtems/score/mips64orion.h | 11 +- c/src/exec/score/cpu/mips64orion/Makefile.am | 7 +- c/src/exec/score/cpu/mips64orion/rtems/Makefile.am | 4 +- .../score/cpu/mips64orion/rtems/score/Makefile.am | 9 +- .../cpu/mips64orion/rtems/score/mips64orion.h | 11 +- c/src/exec/score/cpu/no_cpu/Makefile.am | 7 +- c/src/exec/score/cpu/no_cpu/cpu.c | 24 + c/src/exec/score/cpu/no_cpu/cpu_asm.c | 19 + c/src/exec/score/cpu/no_cpu/rtems.c | 4 + c/src/exec/score/cpu/no_cpu/rtems/Makefile.am | 4 +- .../exec/score/cpu/no_cpu/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/no_cpu/rtems/score/cpu.h | 235 +- c/src/exec/score/cpu/no_cpu/rtems/score/no_cpu.h | 28 +- c/src/exec/score/cpu/powerpc/Makefile.am | 4 +- .../powerpc/new_exception_processing/Makefile.am | 16 +- .../powerpc/old_exception_processing/Makefile.am | 23 +- .../powerpc/old_exception_processing/irq_stub.S | 2 + c/src/exec/score/cpu/powerpc/rtems/score/ppc.h | 50 +- c/src/exec/score/cpu/powerpc/shared/Makefile.am | 8 +- c/src/exec/score/cpu/powerpc/shared/ppc.h | 50 +- c/src/exec/score/cpu/sh/Makefile.am | 7 +- c/src/exec/score/cpu/sh/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/sh/rtems/score/Makefile.am | 13 +- c/src/exec/score/cpu/sh/rtems/score/sh.h | 12 +- c/src/exec/score/cpu/sparc/Makefile.am | 7 +- c/src/exec/score/cpu/sparc/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/sparc/rtems/score/Makefile.am | 9 +- c/src/exec/score/cpu/sparc/rtems/score/sparc.h | 14 +- c/src/exec/score/cpu/unix/Makefile.am | 4 +- c/src/exec/score/cpu/unix/cpu.c | 27 +- c/src/exec/score/cpu/unix/rtems/Makefile.am | 4 +- c/src/exec/score/cpu/unix/rtems/score/Makefile.am | 11 +- c/src/exec/score/cpu/unix/rtems/score/cpu.h | 13 +- c/src/exec/score/cpu/unix/rtems/score/unix.h | 16 +- c/src/exec/score/include/rtems/Makefile.am | 9 +- c/src/exec/score/include/rtems/score/Makefile.am | 17 +- c/src/exec/score/include/rtems/score/thread.h | 3 +- c/src/exec/score/include/rtems/system.h | 4 +- c/src/exec/score/inline/rtems/score/Makefile.am | 9 +- c/src/exec/score/macros/rtems/score/Makefile.am | 16 +- c/src/exec/score/macros/rtems/score/address.inl | 2 +- c/src/exec/score/src/Makefile.am | 3 +- c/src/exec/score/src/objectcopynamestring.c | 9 +- c/src/exec/wrapup/itron/Makefile.am | 5 +- c/src/exec/wrapup/posix/Makefile.am | 7 +- c/src/exec/wrapup/rtems/Makefile.am | 5 +- 291 files changed, 37224 insertions(+), 1500 deletions(-) delete mode 100644 c/src/exec/posix/include/pthread.h (limited to 'c/src/exec') diff --git a/c/src/exec/itron/include/Makefile.am b/c/src/exec/itron/include/Makefile.am index a12590301a..66bdf8c9e7 100644 --- a/c/src/exec/itron/include/Makefile.am +++ b/c/src/exec/itron/include/Makefile.am @@ -8,18 +8,15 @@ H_FILES = itron.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) $(PROJECT_INCLUDE): @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) SUBDIRS = rtems itronsys diff --git a/c/src/exec/itron/include/itronsys/Makefile.am b/c/src/exec/itron/include/itronsys/Makefile.am index 25bcd64a2a..2aa2a0b0ea 100644 --- a/c/src/exec/itron/include/itronsys/Makefile.am +++ b/c/src/exec/itron/include/itronsys/Makefile.am @@ -4,22 +4,19 @@ AUTOMAKE_OPTIONS = foreign 1.4 -H_FILES = eventflags.h fmempool.h intr.h mbox.h msgbuffer.h network.h \ - port.h semaphore.h status.h sysmgmt.h task.h time.h types.h vmempool.h +H_FILES = eventflags.h fmempool.h intr.h mbox.h msgbuffer.h network.h port.h \ + semaphore.h status.h sysmgmt.h task.h time.h types.h vmempool.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/itronsys \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/itronsys/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/itronsys/%) $(PROJECT_INCLUDE)/itronsys: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/itronsys/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/exec/itron/include/rtems/itron/Makefile.am b/c/src/exec/itron/include/rtems/itron/Makefile.am index 542ea135fd..96053cfb9a 100644 --- a/c/src/exec/itron/include/rtems/itron/Makefile.am +++ b/c/src/exec/itron/include/rtems/itron/Makefile.am @@ -5,23 +5,20 @@ AUTOMAKE_OPTIONS = foreign 1.4 H_FILES = config.h eventflags.h fmempool.h intr.h itronapi.h mbox.h \ - msgbuffer.h network.h object.h port.h semaphore.h sysmgmt.h \ - task.h time.h vmempool.h + msgbuffer.h network.h object.h port.h semaphore.h sysmgmt.h task.h \ + time.h vmempool.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/itron \ -$(H_FILES:%=$(PROJECT_INCLUDE)/rtems/itron/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron \ + $(H_FILES:%=$(PROJECT_INCLUDE)/rtems/itron/%) $(PROJECT_INCLUDE)/rtems/itron: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/rtems/itron/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) EXTRA_DIST = README diff --git a/c/src/exec/itron/inline/rtems/itron/Makefile.am b/c/src/exec/itron/inline/rtems/itron/Makefile.am index 659227b218..f5368fff77 100644 --- a/c/src/exec/itron/inline/rtems/itron/Makefile.am +++ b/c/src/exec/itron/inline/rtems/itron/Makefile.am @@ -3,16 +3,16 @@ ## AUTOMAKE_OPTIONS = foreign 1.4 + if INLINE I_FILES = eventflags.inl fmempool.inl intr.inl mbox.inl msgbuffer.inl \ - network.inl port.inl semaphore.inl sysmgmt.inl task.inl \ - time.inl vmempool.inl + network.inl port.inl semaphore.inl sysmgmt.inl task.inl time.inl \ + vmempool.inl noinst_HEADERS = $(I_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/itron \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/itron/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/itron/%) $(PROJECT_INCLUDE)/rtems/itron: @$(mkinstalldirs) $@ @@ -20,8 +20,6 @@ $(PROJECT_INCLUDE)/rtems/itron/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/exec/itron/src/Makefile.am b/c/src/exec/itron/src/Makefile.am index f508440f60..92ae498c69 100644 --- a/c/src/exec/itron/src/Makefile.am +++ b/c/src/exec/itron/src/Makefile.am @@ -18,9 +18,9 @@ EVENTFLAGS_C_FILES = eventflags.c MAILBOX_C_FILES = mbox.c -MSGBUFFER_C_FILES = msgbuffer.c msgbuffertranslatereturncode.c \ - cre_mbf.c del_mbf.c prcv_mbf.c psnd_mbf.c rcv_mbf.c ref_mbf.c snd_mbf.c \ - trcv_mbf.c tsnd_mbf.c +MSGBUFFER_C_FILES = msgbuffer.c msgbuffertranslatereturncode.c cre_mbf.c \ + del_mbf.c prcv_mbf.c psnd_mbf.c rcv_mbf.c ref_mbf.c snd_mbf.c trcv_mbf.c \ + tsnd_mbf.c RENDEZVOUS_C_FILES = port.c @@ -49,20 +49,11 @@ include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../../automake/lib.am AM_CPPFLAGS += -D__RTEMS_INSIDE__ -AM_CFLAGS += $(CFLAGS_OS_V) - -all: ${ARCH} ${OBJS} - -UNUSED_C_FILES = \ -cre_mbx.c del_mbx.c \ -mboxtranslatereturncode.c \ -network.c \ -prcv_mbx.c \ -rcv_mbx.c \ -ref_mbx.c \ -snd_mbx.c \ -sysmgmt.c \ -trcv_mbx.c + +all-local: ${ARCH} ${OBJS} + +UNUSED_C_FILES = cre_mbx.c del_mbx.c mboxtranslatereturncode.c network.c \ + prcv_mbx.c rcv_mbx.c ref_mbx.c snd_mbx.c sysmgmt.c trcv_mbx.c EXTRA_DIST = $(C_FILES) $(UNUSED_C_FILES) diff --git a/c/src/exec/itron/src/cre_tsk.c b/c/src/exec/itron/src/cre_tsk.c index 665e158652..250293c026 100644 --- a/c/src/exec/itron/src/cre_tsk.c +++ b/c/src/exec/itron/src/cre_tsk.c @@ -30,7 +30,6 @@ ER cre_tsk( ) { register Thread_Control *the_thread; - char *name = "trn"; boolean status; Priority_Control core_priority; @@ -90,7 +89,7 @@ ER cre_tsk( THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE, NULL, /* no budget algorithm callout */ 0, - &name + NULL ); if ( !status ) { diff --git a/c/src/exec/itron/src/eventflags.c b/c/src/exec/itron/src/eventflags.c index b7d974ae37..f1a0858e92 100644 --- a/c/src/exec/itron/src/eventflags.c +++ b/c/src/exec/itron/src/eventflags.c @@ -38,7 +38,7 @@ void _ITRON_Eventflags_Manager_initialization( /* control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ /* name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/fmempool.c b/c/src/exec/itron/src/fmempool.c index ec19e6770c..93bbe56af1 100644 --- a/c/src/exec/itron/src/fmempool.c +++ b/c/src/exec/itron/src/fmempool.c @@ -39,7 +39,7 @@ void _ITRON_Fixed_memory_pool_Manager_initialization( /* size of this object's control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ /* name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/itronsem.c b/c/src/exec/itron/src/itronsem.c index ad9278aec2..83686b4a44 100644 --- a/c/src/exec/itron/src/itronsem.c +++ b/c/src/exec/itron/src/itronsem.c @@ -41,7 +41,7 @@ void _ITRON_Semaphore_Manager_initialization( sizeof( ITRON_Semaphore_Control ), /* size of this object's control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ /* name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/mbox.c b/c/src/exec/itron/src/mbox.c index a8dd9a26ca..6d2deb8819 100644 --- a/c/src/exec/itron/src/mbox.c +++ b/c/src/exec/itron/src/mbox.c @@ -40,7 +40,7 @@ void _ITRON_Mailbox_Manager_initialization( sizeof( ITRON_Mailbox_Control ), /* size of this object's control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ /* name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/msgbuffer.c b/c/src/exec/itron/src/msgbuffer.c index 13c89efba6..e4cb4a4f20 100644 --- a/c/src/exec/itron/src/msgbuffer.c +++ b/c/src/exec/itron/src/msgbuffer.c @@ -43,7 +43,7 @@ void _ITRON_Message_buffer_Manager_initialization( block */ FALSE, /* TRUE if names for this object are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/port.c b/c/src/exec/itron/src/port.c index 0e9d98eb04..df360e155d 100644 --- a/c/src/exec/itron/src/port.c +++ b/c/src/exec/itron/src/port.c @@ -36,7 +36,7 @@ void _ITRON_Port_Manager_initialization( sizeof( ITRON_Port_Control ), /* size of this object's control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's name */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/itron/src/vmempool.c b/c/src/exec/itron/src/vmempool.c index d1a7d8a4a7..7f0ee73021 100644 --- a/c/src/exec/itron/src/vmempool.c +++ b/c/src/exec/itron/src/vmempool.c @@ -39,7 +39,7 @@ void _ITRON_Variable_memory_pool_Manager_initialization( /* size of this object's control block */ FALSE, /* TRUE if names for this object */ /* are strings */ - RTEMS_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ + ITRON_MAXIMUM_NAME_LENGTH, /* maximum length of each object's */ /* name */ FALSE /* TRUE if this class is threads */ ); diff --git a/c/src/exec/libcsupport/Makefile.am b/c/src/exec/libcsupport/Makefile.am index f65729290b..2d2f16cd26 100644 --- a/c/src/exec/libcsupport/Makefile.am +++ b/c/src/exec/libcsupport/Makefile.am @@ -5,8 +5,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal -SUBDIRS = include libc libcpu libbsp \ - $(LIBHWAPI) +SUBDIRS = include libc libcpu libbsp include $(top_srcdir)/../../../automake/subdirs.am include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libcsupport/include/console.h b/c/src/exec/libcsupport/include/console.h index 7bc6b5e3d4..2d2f380012 100644 --- a/c/src/exec/libcsupport/include/console.h +++ b/c/src/exec/libcsupport/include/console.h @@ -24,10 +24,6 @@ extern "C" { { console_initialize, console_open, console_close, \ console_read, console_write, console_control } -void console_reserve_resources( - rtems_configuration_table *configuration -); - rtems_device_driver console_initialize( rtems_device_major_number, rtems_device_minor_number, diff --git a/c/src/exec/libcsupport/include/rtems/error.h b/c/src/exec/libcsupport/include/rtems/error.h index a0698afb5d..de6e1715db 100644 --- a/c/src/exec/libcsupport/include/rtems/error.h +++ b/c/src/exec/libcsupport/include/rtems/error.h @@ -7,6 +7,10 @@ #ifndef __RTEMS_ERROR_h #define __RTEMS_ERROR_h +#ifdef __cplusplus +extern "C" { +#endif + /* * rtems_error() and rtems_panic() support */ @@ -34,5 +38,10 @@ void rtems_panic(const char *printf_format, ...); extern int rtems_panic_in_progress; +#ifdef __cplusplus +} +#endif + + #endif /* end of include file */ diff --git a/c/src/exec/libcsupport/include/sys/termios.h b/c/src/exec/libcsupport/include/sys/termios.h index bb64d55433..7cc28d7d38 100644 --- a/c/src/exec/libcsupport/include/sys/termios.h +++ b/c/src/exec/libcsupport/include/sys/termios.h @@ -14,6 +14,8 @@ #ifndef TERMIOS_H #define TERMIOS_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -174,9 +176,15 @@ struct termios { #define TCSADRAIN 1 #define TCSAFLUSH 2 +int tcdrain(int); +int tcflow(int, int); +int tcflush(int, int); int tcgetattr(int, struct termios *); int tcsetattr(int, int, struct termios *); -int tcdrain(int); +pid_t tcgetprgrp(int); +int tcsetprgrp(int, pid_t); +int tcsendbreak(int, int); + speed_t cfgetospeed(const struct termios *tp); int cfsetospeed(struct termios *tp, speed_t speed); speed_t cfgetispeed(const struct termios *tp); diff --git a/c/src/exec/libcsupport/src/Makefile.am b/c/src/exec/libcsupport/src/Makefile.am index 20893f29eb..54b674b2f7 100644 --- a/c/src/exec/libcsupport/src/Makefile.am +++ b/c/src/exec/libcsupport/src/Makefile.am @@ -48,15 +48,14 @@ LIBC_GLUE_C_FILES = __getpid.c __gettod.c __times.c truncate.c access.c \ UNIX_LIBC_C_FILES = unixlibc.c hosterr.c -COMMON_C_FILES = $(BASE_FS_C_FILES) $(MALLOC_C_FILES) \ - $(TERMIOS_C_FILES) $(ERROR_C_FILES) $(ASSOCIATION_C_FILES) +COMMON_C_FILES = gxx_wrappers.c $(BASE_FS_C_FILES) $(MALLOC_C_FILES) $(TERMIOS_C_FILES) \ + $(ERROR_C_FILES) $(ASSOCIATION_C_FILES) UNIX_C_FILES = $(UNIX_LIBC_C_FILES) imfs_unixstub.c -EMBEDDED_C_FILES = $(LIBC_GLUE_C_FILES) \ - $(PASSWORD_GROUP_C_FILES) $(TERMINAL_IDENTIFICATION_C_FILES) \ - $(SYSTEM_CALL_C_FILES) $(DIRECTORY_SCAN_C_FILES) \ - $(IMFS_C_FILES) +EMBEDDED_C_FILES = $(LIBC_GLUE_C_FILES) $(PASSWORD_GROUP_C_FILES) \ + $(TERMINAL_IDENTIFICATION_C_FILES) $(SYSTEM_CALL_C_FILES) \ + $(DIRECTORY_SCAN_C_FILES) $(IMFS_C_FILES) if UNIX C_FILES = $(COMMON_C_FILES) $(UNIX_C_FILES) @@ -73,13 +72,10 @@ noinst_HEADERS = libio_.h include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../automake/lib.am -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(PROJECT_INCLUDE)/rtems \ -$(PROJECT_INCLUDE)/sys \ -$(H_FILES:%=$(PROJECT_INCLUDE)/%) \ -$(RTEMS_H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) \ -$(SYS_H_FILES:%=$(PROJECT_INCLUDE)/sys/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems \ + $(PROJECT_INCLUDE)/sys $(H_FILES:%=$(PROJECT_INCLUDE)/%) \ + $(RTEMS_H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) \ + $(SYS_H_FILES:%=$(PROJECT_INCLUDE)/sys/%) $(PROJECT_INCLUDE): @$(mkinstalldirs) $@ @@ -95,8 +91,7 @@ $(PROJECT_INCLUDE)/rtems/%.h: %.h $(PROJECT_INCLUDE)/sys/%.h: %.h $(INSTALL_DATA) $< $@ -TMPINSTALL_FILES += \ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a OBJS = $(C_O_FILES) @@ -106,7 +101,7 @@ OBJS = $(C_O_FILES) AM_CFLAGS += $(LIBC_DEFINES) -all: ${ARCH} $(TMPINSTALL_FILES) +all-local: ${ARCH} $(TMPINSTALL_FILES) $(LIB): ${OBJS} $(make-library) @@ -116,9 +111,7 @@ $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) DOC_FILES = TODO CASES -EXTRA_DIST = \ -$(DOC_FILES) \ -$(COMMON_C_FILES) $(EMBEDDED_C_FILES) $(UNIX_C_FILES) \ -$(H_FILES) $(RTEMS_H_FILES) $(SYS_H_FILES) +EXTRA_DIST = $(DOC_FILES) $(COMMON_C_FILES) $(EMBEDDED_C_FILES) \ + $(UNIX_C_FILES) $(H_FILES) $(RTEMS_H_FILES) $(SYS_H_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libcsupport/src/gxx_wrappers.c b/c/src/exec/libcsupport/src/gxx_wrappers.c index e69de29bb2..323da73e7f 100644 --- a/c/src/exec/libcsupport/src/gxx_wrappers.c +++ b/c/src/exec/libcsupport/src/gxx_wrappers.c @@ -0,0 +1,219 @@ +/* + * RTEMS threads compatibily routines for libgcc2. + * + * by: Rosimildo da Silva ( rdasilva@connecttel.com + * + * Used ideas from: + * W. Eric Norum + * Canadian Light Source + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@cls.usask.ca + * + * Eric sent some e-mail in the rtems-list as a start point for this + * module implementation. + * + * + */ + +/* We might not need, defined just in case */ +#define __RTEMS_INSIDE__ 1 + + +#include +#include + +#include +#include +#include + +/* + * These typedefs should match with the ones defined in the file + * gcc/gthr-rtems.h in the gcc distribution. + */ +typedef void *__gthread_key_t; +typedef int __gthread_once_t; +typedef void *__gthread_mutex_t; + + +/* uncomment this if you need to debug this interface */ + +/* +#define DEBUG_GXX_WRAPPERS 1 +*/ + + +/* prototype for the terminate() */ +extern void __terminate( void ); + + +#ifdef DEBUG_GXX_WRAPPERS +/* local function to return the ID of the calling thread */ +static rtems_id get_tid( void ) +{ + rtems_id id = 0; + rtems_task_ident( RTEMS_SELF, 0, &id ); + return id; +} +#endif + + +int rtems_gxx_once(__gthread_once_t *once, void (*func) ()) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: once=%x, func=%x\n", *once, func ); +#endif + if( *once == 0 ) + { + /* + * NOTE: could not use the call to disable "preemption", it causes + * one exception. Somebody might want to investiage it further + * sometime later. + */ + _Thread_Disable_dispatch(); + *once = 1; + (*func)(); + _Thread_Enable_dispatch(); + } + return 0; +} + + +int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *)) +{ + /* Ok, this can be a bit tricky. We are going to return a "key" as a + * pointer to the buffer that will hold the value of the key itself. + * We have to to this, becuase the others functions on this interface + * deal with the value of the key, as used with the POSIX API. + */ + /* Do not pull your hair, trust me this works. :-) */ + __gthread_key_t *new_key = ( __gthread_key_t * )malloc( sizeof( __gthread_key_t ) ); + *key = ( __gthread_key_t )new_key; + *new_key = NULL; + +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key ); +#endif + /* register with RTEMS the buffer that will hold the key values */ + if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, NULL ) == RTEMS_SUCCESSFUL ) + return 0; + return -1; +} + +int rtems_gxx_key_dtor (__gthread_key_t key, void *ptr) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr ); +#endif + *(void **)key = 0; + return 0; +} + +int rtems_gxx_key_delete (__gthread_key_t key) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: delete key=%x\n", key ); +#endif + /* register with RTEMS the buffer that will hold the key values */ + if( rtems_task_variable_delete( RTEMS_SELF, (void **)key ) == RTEMS_SUCCESSFUL ) + { + if( key ) free( (void *)key ); + return 0; + } + return 0; +} + + +void *rtems_gxx_getspecific(__gthread_key_t key) +{ + void *p= 0; + + /* register with RTEMS the buffer that will hold the key values */ + if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == RTEMS_SUCCESSFUL ) + { + /* We do not have to do this, but what the heck ! */ + p= *( void **)key; + } + else + { + /* fisrt time, always set to zero, it is unknown the value that the others + * threads are using at the moment of this call + */ + if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) != RTEMS_SUCCESSFUL ) + { + __terminate (); + } + *( void ** )key = (void *)0; + } + +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n", key, p, get_tid() ); +#endif + return p; +} + + +int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() ); +#endif + /* register with RTEMS the buffer that will hold the key values */ + if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) == RTEMS_SUCCESSFUL ) + { + /* now let's set the proper value */ + *( void ** )key = (void *)ptr; + return 0; + } + return -1; +} + + +/* + * MUTEX support + */ +void rtems_gxx_mutex_init (__gthread_mutex_t *mutex) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: mutex init =%X\n", *mutex ); +#endif + if( rtems_semaphore_create( rtems_build_name ('G', 'C', 'C', '2'), + 1, + RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE + |RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL, + 0, + (rtems_id *)mutex ) != RTEMS_SUCCESSFUL ) + { + __terminate (); + } +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: mutex init complete =%X\n", *mutex ); +#endif +} + +int rtems_gxx_mutex_lock (__gthread_mutex_t *mutex) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: lock mutex=%X\n", *mutex ); +#endif + return ( rtems_semaphore_obtain( (rtems_id)*mutex, + RTEMS_WAIT, RTEMS_NO_TIMEOUT ) == RTEMS_SUCCESSFUL) ? 0 : -1; +} + +int rtems_gxx_mutex_trylock (__gthread_mutex_t *mutex) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: trylock mutex=%X\n", *mutex ); +#endif + return (rtems_semaphore_obtain ((rtems_id)*mutex, + RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL) ? 0 : -1; +} + +int rtems_gxx_mutex_unlock (__gthread_mutex_t *mutex) +{ +#ifdef DEBUG_GXX_WRAPPERS + printk( "gxx_wrappers: unlock mutex=%X\n", *mutex ); +#endif + return (rtems_semaphore_release( (rtems_id)*mutex ) == RTEMS_SUCCESSFUL) ? 0 :-1; +} + diff --git a/c/src/exec/libcsupport/src/libio.c b/c/src/exec/libcsupport/src/libio.c index 9e075c9f0b..c878db6247 100644 --- a/c/src/exec/libcsupport/src/libio.c +++ b/c/src/exec/libcsupport/src/libio.c @@ -260,7 +260,7 @@ int rtems_libio_is_open_files_in_fs( * Look for any active file descriptor entry. */ - for (iop=rtems_libio_iops,i=0; i <= rtems_libio_number_iops; iop++, i++){ + for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { @@ -304,7 +304,7 @@ int rtems_libio_is_file_open( * Look for any active file descriptor entry. */ - for (iop=rtems_libio_iops,i=0; i <= rtems_libio_number_iops; iop++, i++){ + for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { /* diff --git a/c/src/exec/libcsupport/src/malloc.c b/c/src/exec/libcsupport/src/malloc.c index cc63b6c7d0..08660d75cc 100644 --- a/c/src/exec/libcsupport/src/malloc.c +++ b/c/src/exec/libcsupport/src/malloc.c @@ -120,7 +120,7 @@ void RTEMS_Malloc_Initialize( rtems_build_name( 'H', 'E', 'A', 'P' ), starting_address, length, - CPU_ALIGNMENT, + CPU_HEAP_ALIGNMENT, RTEMS_DEFAULT_ATTRIBUTES, &RTEMS_Malloc_Heap ); diff --git a/c/src/exec/libcsupport/src/scandir.c b/c/src/exec/libcsupport/src/scandir.c index 43c7c51747..25f3263187 100644 --- a/c/src/exec/libcsupport/src/scandir.c +++ b/c/src/exec/libcsupport/src/scandir.c @@ -112,7 +112,7 @@ scandir(dirname, namelist, select, dcomp) p->d_ino = d->d_ino; p->d_reclen = d->d_reclen; p->d_namlen = d->d_namlen; - strncpy(p->d_name, d->d_name, p->d_namlen + 1); + strncpy(d->d_name, p->d_name, p->d_namlen + 1); /* * Check to make sure the array has space left and * realloc the maximum size. diff --git a/c/src/exec/libcsupport/src/termios.c b/c/src/exec/libcsupport/src/termios.c index 6d334ecd23..7883e94b63 100644 --- a/c/src/exec/libcsupport/src/termios.c +++ b/c/src/exec/libcsupport/src/termios.c @@ -28,7 +28,6 @@ * FreeBSD does not support a full POSIX termios so we have to help it out */ - #if defined(__FreeBSD__) #define XTABS 0 #define ONLRET 0 @@ -40,6 +39,14 @@ #define IUCLC 0 #endif +/* + * Cygwin does not define these + */ + +#if defined(__CYGWIN__) +#define ECHOPRT 0 +#endif + /* * The size of the cooked buffer */ @@ -238,7 +245,7 @@ rtems_termios_open ( */ tty->termios.c_iflag = BRKINT | ICRNL | IMAXBEL; tty->termios.c_oflag = OPOST | ONLCR | XTABS; - tty->termios.c_cflag = B9600 | CS8 | CREAD; + tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; tty->termios.c_cc[VINTR] = '\003'; @@ -256,8 +263,8 @@ rtems_termios_open ( tty->termios.c_cc[VWERASE] = '\027'; tty->termios.c_cc[VLNEXT] = '\026'; - /* setup flow control mode, clear flow control flags */ - tty->flow_ctrl = FL_MDXON; + /* start with no flow control, clear flow control flags */ + tty->flow_ctrl = 0; /* * set low/highwater mark for XON/XOFF support */ diff --git a/c/src/exec/libcsupport/src/termiosreserveresources.c b/c/src/exec/libcsupport/src/termiosreserveresources.c index 2d9c05c988..664bdd1f62 100644 --- a/c/src/exec/libcsupport/src/termiosreserveresources.c +++ b/c/src/exec/libcsupport/src/termiosreserveresources.c @@ -6,15 +6,19 @@ #include +#if 0 static int first_time; /* assumed to be zeroed by BSS initialization */ +#endif void rtems_termios_reserve_resources ( rtems_configuration_table *configuration, rtems_unsigned32 number_of_devices ) { +#if 0 rtems_api_configuration_table *rtems_config; + if (!configuration) rtems_fatal_error_occurred (0xFFF0F001); rtems_config = configuration->RTEMS_api_configuration; @@ -24,5 +28,6 @@ void rtems_termios_reserve_resources ( rtems_config->maximum_semaphores += 1; first_time = 1; rtems_config->maximum_semaphores += (4 * number_of_devices); +#endif } diff --git a/c/src/exec/libcsupport/src/unmount.c b/c/src/exec/libcsupport/src/unmount.c index c4b6bdae7d..46b11d1848 100644 --- a/c/src/exec/libcsupport/src/unmount.c +++ b/c/src/exec/libcsupport/src/unmount.c @@ -62,7 +62,6 @@ int unmount( int status; rtems_filesystem_location_info_t temp_loc; rtems_filesystem_mount_table_entry_t temp_mt_entry; - int result; /* * Are there any file systems below the mount_path specified @@ -101,7 +100,7 @@ int unmount( /* * Allow the file system being mounted on to do its cleanup. * XXX - Did I change these correctly ??? It looks like either I did - * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swaped. + * XXX this backwards or the IMFS_unmount and IMFS_fsumount are swapped. * XXX Add to the mt_point_node unmount to set the mt_entry back to null * XXX I will step off in space when evaluating past the end of the node. */ @@ -120,12 +119,6 @@ int unmount( return -1; } - /* - * Allow the file system to clean up. - */ - - result = (*temp_loc.ops->fsunmount_me)( temp_loc.mt_entry ); - /* * Extract the mount table entry from the chain */ @@ -140,8 +133,7 @@ int unmount( free( temp_loc.mt_entry ); rtems_filesystem_freenode( &temp_loc ); - return result; - + return 0; } diff --git a/c/src/exec/libfs/src/imfs/imfs.h b/c/src/exec/libfs/src/imfs/imfs.h index 38c770a325..3a44c50ee3 100644 --- a/c/src/exec/libfs/src/imfs/imfs.h +++ b/c/src/exec/libfs/src/imfs/imfs.h @@ -157,9 +157,9 @@ struct IMFS_jnode_tt { uid_t st_uid; /* User ID of owner */ gid_t st_gid; /* Group ID of owner */ - time_t st_atime; /* Time of last access */ - time_t st_mtime; /* Time of last modification */ - time_t st_ctime; /* Time of last status change */ + time_t stat_atime; /* Time of last access */ + time_t stat_mtime; /* Time of last modification */ + time_t stat_ctime; /* Time of last status change */ IMFS_jnode_types_t type; /* Type of this entry */ IMFS_types_union info; }; @@ -168,29 +168,29 @@ struct IMFS_jnode_tt { do { \ struct timeval tv; \ gettimeofday( &tv, 0 ); \ - _jnode->st_atime = (time_t) tv.tv_sec; \ + _jnode->stat_atime = (time_t) tv.tv_sec; \ } while (0) #define IMFS_update_mtime( _jnode ) \ do { \ struct timeval tv; \ gettimeofday( &tv, 0 ); \ - _jnode->st_mtime = (time_t) tv.tv_sec; \ + _jnode->stat_mtime = (time_t) tv.tv_sec; \ } while (0) #define IMFS_update_ctime( _jnode ) \ do { \ struct timeval tv; \ gettimeofday( &tv, 0 ); \ - _jnode->st_ctime = (time_t) tv.tv_sec; \ + _jnode->stat_ctime = (time_t) tv.tv_sec; \ } while (0) #define IMFS_atime_mtime_update( _jnode ) \ do { \ struct timeval tv; \ gettimeofday( &tv, 0 ); \ - _jnode->st_mtime = (time_t) tv.tv_sec; \ - _jnode->st_atime = (time_t) tv.tv_sec; \ + _jnode->stat_mtime = (time_t) tv.tv_sec; \ + _jnode->stat_atime = (time_t) tv.tv_sec; \ } while (0) typedef struct { diff --git a/c/src/exec/libfs/src/imfs/imfs_creat.c b/c/src/exec/libfs/src/imfs/imfs_creat.c index 227b5f9300..b60e78540e 100644 --- a/c/src/exec/libfs/src/imfs/imfs_creat.c +++ b/c/src/exec/libfs/src/imfs/imfs_creat.c @@ -72,9 +72,9 @@ IMFS_jnode_t *IMFS_create_node( gettimeofday( &tv, 0 ); - node->st_atime = (time_t) tv.tv_sec; - node->st_mtime = (time_t) tv.tv_sec; - node->st_ctime = (time_t) tv.tv_sec; + node->stat_atime = (time_t) tv.tv_sec; + node->stat_mtime = (time_t) tv.tv_sec; + node->stat_ctime = (time_t) tv.tv_sec; /* * Set the type specific information diff --git a/c/src/exec/libfs/src/imfs/imfs_directory.c b/c/src/exec/libfs/src/imfs/imfs_directory.c index 1f6d9b5ff5..38280c565c 100644 --- a/c/src/exec/libfs/src/imfs/imfs_directory.c +++ b/c/src/exec/libfs/src/imfs/imfs_directory.c @@ -219,9 +219,9 @@ int imfs_dir_lseek( * dirent structure * st_blksize 0 * st_blocks 0 - * st_atime time of last access - * st_mtime time of last modification - * st_ctime time of the last change + * stat_atime time of last access + * stat_mtime time of last modification + * stat_ctime time of the last change * * This information will be returned to the calling function in a -stat- struct * @@ -248,9 +248,9 @@ int imfs_dir_fstat( buf->st_rdev = 0ll; buf->st_blksize = 0; buf->st_blocks = 0; - buf->st_atime = the_jnode->st_atime; - buf->st_mtime = the_jnode->st_mtime; - buf->st_ctime = the_jnode->st_ctime; + buf->st_atime = the_jnode->stat_atime; + buf->st_mtime = the_jnode->stat_mtime; + buf->st_ctime = the_jnode->stat_ctime; buf->st_size = 0; diff --git a/c/src/exec/libfs/src/imfs/imfs_stat.c b/c/src/exec/libfs/src/imfs/imfs_stat.c index 2edc1a9e9b..f5858498c1 100644 --- a/c/src/exec/libfs/src/imfs/imfs_stat.c +++ b/c/src/exec/libfs/src/imfs/imfs_stat.c @@ -50,9 +50,9 @@ int IMFS_stat( buf->st_uid = the_jnode->st_uid; buf->st_gid = the_jnode->st_gid; - buf->st_atime = the_jnode->st_atime; - buf->st_mtime = the_jnode->st_mtime; - buf->st_ctime = the_jnode->st_ctime; + buf->st_atime = the_jnode->stat_atime; + buf->st_mtime = the_jnode->stat_mtime; + buf->st_ctime = the_jnode->stat_ctime; return 0; } diff --git a/c/src/exec/libfs/src/imfs/imfs_utime.c b/c/src/exec/libfs/src/imfs/imfs_utime.c index e20d352c50..c9bd9ddd90 100644 --- a/c/src/exec/libfs/src/imfs/imfs_utime.c +++ b/c/src/exec/libfs/src/imfs/imfs_utime.c @@ -30,8 +30,8 @@ int IMFS_utime( the_jnode = (IMFS_jnode_t *) pathloc->node_access; - the_jnode->st_atime = actime; - the_jnode->st_mtime = modtime; + the_jnode->stat_atime = actime; + the_jnode->stat_mtime = modtime; return 0; } diff --git a/c/src/exec/libnetworking/Makefile.am b/c/src/exec/libnetworking/Makefile.am index ce9cf6c399..7e41fce2b3 100644 --- a/c/src/exec/libnetworking/Makefile.am +++ b/c/src/exec/libnetworking/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -9,7 +9,7 @@ SUBDIRS = include arpa kern machine sys vm lib libc net netinet nfs rtems \ rtems_servers pppd rtems_webserver wrapup EXTRA_DIST = CHANGELOG bpfilter.h loop.h netdb.h opt_ipfw.h opt_mrouting.h \ - opt_tcpdebug.h poll.h resolv.h syslog.h + opt_tcpdebug.h poll.h resolv.h syslog.h memory.h include $(top_srcdir)/../../../automake/subdirs.am include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/arpa/Makefile.am b/c/src/exec/libnetworking/arpa/Makefile.am index dba97b83d5..6ee4bfbe74 100644 --- a/c/src/exec/libnetworking/arpa/Makefile.am +++ b/c/src/exec/libnetworking/arpa/Makefile.am @@ -4,6 +4,18 @@ AUTOMAKE_OPTIONS = foreign 1.4 -EXTRA_DIST = ftp.h inet.h nameser.h nameser_compat.h telnet.h +H_FILES = ftp.h inet.h nameser.h nameser_compat.h telnet.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa $(H_FILES:%=$(PROJECT_INCLUDE)/arpa/%) + +$(PROJECT_INCLUDE)/arpa: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/arpa/%.h: %.h + $(INSTALL_DATA) $< $@ + +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/kern/Makefile.am b/c/src/exec/libnetworking/kern/Makefile.am index aedc2bbadf..878f23612e 100644 --- a/c/src/exec/libnetworking/kern/Makefile.am +++ b/c/src/exec/libnetworking/kern/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/libnetworking/lib/Makefile.am b/c/src/exec/libnetworking/lib/Makefile.am index 5f8d151e13..64e3a0e8f4 100644 --- a/c/src/exec/libnetworking/lib/Makefile.am +++ b/c/src/exec/libnetworking/lib/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/libnetworking/lib/rtems_bsdnet_ntp.c b/c/src/exec/libnetworking/lib/rtems_bsdnet_ntp.c index 11b0cef63a..54974aa332 100644 --- a/c/src/exec/libnetworking/lib/rtems_bsdnet_ntp.c +++ b/c/src/exec/libnetworking/lib/rtems_bsdnet_ntp.c @@ -111,7 +111,7 @@ rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority) printf ("Can't set socket receive timeout: %s", strerror (errno)); return -1; } - memset (&myAddr, sizeof myAddr, 0); + memset (&myAddr, 0, sizeof myAddr); myAddr.sin_family = AF_INET; myAddr.sin_port = htons (123); myAddr.sin_addr.s_addr = htonl (INADDR_ANY); @@ -126,14 +126,14 @@ rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority) * server out there somewhere. */ if (rtems_bsdnet_ntpserver_count > 0) { - memset (&farAddr, sizeof farAddr, 0); + memset (&farAddr, 0, sizeof farAddr); farAddr.sin_family = AF_INET; farAddr.sin_port = htons (123); /* * For now, try only the first server. */ farAddr.sin_addr = rtems_bsdnet_ntpserver[0]; - memset (&packet, sizeof packet, 0); + memset (&packet, 0, sizeof packet); packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */ i = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr); if (i != sizeof packet) { diff --git a/c/src/exec/libnetworking/libc/Makefile.am b/c/src/exec/libnetworking/libc/Makefile.am index 57b2b412f2..aca9052ee2 100644 --- a/c/src/exec/libnetworking/libc/Makefile.am +++ b/c/src/exec/libnetworking/libc/Makefile.am @@ -1,20 +1,21 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 no-installman LIBNAME = lib.a LIB = $(ARCH)/$(LIBNAME) -C_FILES = base64.c gethostbydns.c gethostbyht.c gethostbynis.c \ - gethostnamadr.c getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \ - getproto.c getprotoent.c getprotoname.c getservbyname.c getservbyport.c \ - getservent.c herror.c inet_addr.c inet_lnaof.c inet_makeaddr.c \ - inet_network.c inet_ntoa.c inet_ntop.c inet_pton.c map_v4v6.c \ - nsap_addr.c ns_name.c ns_netint.c ns_parse.c ns_print.c ns_ttl.c \ - res_comp.c res_data.c res_debug.c res_init.c res_mkquery.c \ - res_mkupdate.c res_query.c res_send.c res_stubs.c res_update.c strsep.c +C_FILES = addr2ascii.c ascii2addr.c base64.c gethostbydns.c gethostbyht.c \ + gethostbynis.c gethostnamadr.c getnetbydns.c getnetbyht.c getnetbynis.c \ + getnetnamadr.c getproto.c getprotoent.c getprotoname.c getservbyname.c \ + getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \ + inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \ + inet_pton.c linkaddr.c map_v4v6.c nsap_addr.c ns_name.c ns_netint.c \ + ns_parse.c ns_print.c ns_ttl.c res_comp.c res_data.c res_debug.c \ + res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \ + res_stubs.c res_update.c strsep.c C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) OBJS = $(C_O_FILES) @@ -30,8 +31,7 @@ man_MANS = addr2ascii.3 byteorder.3 ethers.3 gethostbyname.3 getnetent.3 \ # Add local stuff here using += # -AM_CPPFLAGS += -DNOPOLL -DNOSELECT -AM_CPPFLAGS += -U__STRICT_ANSI__ +AM_CPPFLAGS += -DNOPOLL -DNOSELECT -U__STRICT_ANSI__ $(LIB): $(OBJS) $(make-library) @@ -47,7 +47,7 @@ EXTRA_DIST = addr2ascii.3 addr2ascii.c ascii2addr.c base64.c byteorder.3 \ getprotoent.c getprotoname.c getservbyname.c getservbyport.c \ getservent.3 getservent.c herror.c inet.3 inet_addr.c inet_lnaof.c \ inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c inet_netof.c \ - inet_network.c inet_ntoa.c inet_ntop.c inet_pton.c iso_addr.3 iso_addr.c \ + inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c inet_pton.c map_v4v6.c \ linkaddr.3 linkaddr.c map_v4v6.c ns.3 ns_addr.c ns_name.c ns_netint.c \ ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c rcmd.3 rcmd.c \ recv.c res_comp.c res_config.h res_data.c res_debug.c res_init.c \ diff --git a/c/src/exec/libnetworking/machine/Makefile.am b/c/src/exec/libnetworking/machine/Makefile.am index 11e23bf86c..e703d0b82b 100644 --- a/c/src/exec/libnetworking/machine/Makefile.am +++ b/c/src/exec/libnetworking/machine/Makefile.am @@ -1,10 +1,23 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 -EXTRA_DIST = conf.h cpu.h cpufunc.h endian.h in_cksum.h limits.h param.h \ +H_FILES = conf.h cpu.h cpufunc.h endian.h in_cksum.h limits.h param.h \ types.h vmparam.h +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine \ + $(H_FILES:%=$(PROJECT_INCLUDE)/machine/%) + +$(PROJECT_INCLUDE)/machine: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/machine/%.h: %.h + $(INSTALL_DATA) $< $@ + +all-local: $(PREINSTALL_FILES) + include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/memory.h b/c/src/exec/libnetworking/memory.h index e69de29bb2..7ef4cda388 100644 --- a/c/src/exec/libnetworking/memory.h +++ b/c/src/exec/libnetworking/memory.h @@ -0,0 +1,5 @@ +/* + * Dummy include file for FreeBSD routines + */ + +#include diff --git a/c/src/exec/libnetworking/net/Makefile.am b/c/src/exec/libnetworking/net/Makefile.am index d965963974..eda18a9c76 100644 --- a/c/src/exec/libnetworking/net/Makefile.am +++ b/c/src/exec/libnetworking/net/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -26,12 +26,24 @@ AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ $(LIB): $(OBJS) $(make-library) -all-local: $(ARCH) $(OBJS) $(LIB) +all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) .PRECIOUS: $(LIB) -EXTRA_DIST = bpf.h ethernet.h if.c if.h if_arp.h if_dl.h if_ethersubr.c \ - if_llc.h if_loop.c if_ppp.h if_types.h netisr.h ppp-comp.h ppp_defs.h \ - radix.c radix.h raw_cb.c raw_cb.h raw_usrreq.c route.c route.h rtsock.c +EXTRA_DIST = if.c if_ethersubr.c if_loop.c \ + radix.c raw_cb.c raw_usrreq.c route.c rtsock.c + +H_FILES = bpf.h ethernet.h if.h if_arp.h if_dl.h if_llc.h if_ppp.h if_types.h \ + netisr.h ppp-comp.h ppp_defs.h radix.h raw_cb.h route.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/net $(H_FILES:%=$(PROJECT_INCLUDE)/net/%) + +$(PROJECT_INCLUDE)/net: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/net/%.h: %.h + $(INSTALL_DATA) $< $@ include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/net/if_loop.c b/c/src/exec/libnetworking/net/if_loop.c index 3823c28744..345730c729 100644 --- a/c/src/exec/libnetworking/net/if_loop.c +++ b/c/src/exec/libnetworking/net/if_loop.c @@ -118,6 +118,7 @@ rtems_bsdnet_loopattach(dummy) ifp->if_type = IFT_LOOP; ifp->if_hdrlen = 0; ifp->if_addrlen = 0; + ifp->if_snd.ifq_maxlen = ifqmaxlen; if_attach(ifp); #if NBPFILTER > 0 bpfattach(ifp, DLT_NULL, sizeof(u_int)); diff --git a/c/src/exec/libnetworking/netinet/Makefile.am b/c/src/exec/libnetworking/netinet/Makefile.am index f967b65cd7..dedeb31ac7 100644 --- a/c/src/exec/libnetworking/netinet/Makefile.am +++ b/c/src/exec/libnetworking/netinet/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -28,16 +28,30 @@ AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ $(LIB): $(OBJS) $(make-library) -all-local: $(ARCH) $(OBJS) $(LIB) +all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) .PRECIOUS: $(LIB) -EXTRA_DIST = icmp_var.h if_ether.c if_ether.h igmp.c igmp.h igmp_var.h in.c \ - in.h in_cksum.c in_cksum_i386.c in_cksum_m68k.c in_cksum_powerpc.c \ - in_pcb.c in_pcb.h in_proto.c in_rmx.c in_systm.h in_var.h ip.h \ - ip_divert.c ip_fw.c ip_fw.h ip_icmp.c ip_icmp.h ip_input.c ip_mroute.c \ - ip_mroute.h ip_output.c ip_var.h raw_ip.c tcp.h tcp_debug.c tcp_debug.h \ - tcp_fsm.h tcp_input.c tcp_output.c tcp_seq.h tcp_subr.c tcp_timer.c \ - tcp_timer.h tcp_usrreq.c tcp_var.h tcpip.h udp.h udp_usrreq.c udp_var.h +EXTRA_DIST = if_ether.c igmp.c igmp_var.h in.c in_cksum.c in_cksum_i386.c \ + in_cksum_m68k.c in_cksum_powerpc.c in_pcb.c in_proto.c in_rmx.c \ + ip_divert.c ip_fw.c ip_icmp.c ip_input.c ip_mroute.c ip_output.c \ + raw_ip.c tcp_debug.c tcp_input.c tcp_output.c tcp_subr.c tcp_timer.c \ + tcp_usrreq.c udp_usrreq.c + +H_FILES = icmp_var.h if_ether.h igmp.h igmp_var.h in.h \ + in_pcb.h in_systm.h in_var.h ip.h ip_fw.h ip_icmp.h \ + ip_mroute.h ip_var.h tcp.h tcp_debug.h tcp_fsm.h tcp_seq.h \ + tcp_timer.h tcp_var.h tcpip.h udp.h udp_var.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet \ + $(H_FILES:%=$(PROJECT_INCLUDE)/netinet/%) + +$(PROJECT_INCLUDE)/netinet: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/netinet/%.h: %.h + $(INSTALL_DATA) $< $@ include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/netinet/in.h b/c/src/exec/libnetworking/netinet/in.h index ba3cbb21cc..36d2d4e867 100644 --- a/c/src/exec/libnetworking/netinet/in.h +++ b/c/src/exec/libnetworking/netinet/in.h @@ -255,6 +255,9 @@ struct in_addr { #define INADDR_MAX_LOCAL_GROUP (u_long)0xe00000ff /* 224.0.0.255 */ #define IN_LOOPBACKNET 127 /* official! */ +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 /* 127.0.0.1 */ +#endif /* * Socket address, internet style. diff --git a/c/src/exec/libnetworking/nfs/Makefile.am b/c/src/exec/libnetworking/nfs/Makefile.am index 51184e47ae..9a8b43e31a 100644 --- a/c/src/exec/libnetworking/nfs/Makefile.am +++ b/c/src/exec/libnetworking/nfs/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -25,11 +25,23 @@ AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ $(LIB): $(OBJS) $(make-library) -all-local: $(ARCH) $(OBJS) $(LIB) +all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) .PRECIOUS: $(LIB) -EXTRA_DIST = bootp_subr.c krpc.h nfs.h nfsdiskless.h nfsproto.h rpcv2.h \ - xdr_subs.h +EXTRA_DIST = bootp_subr.c + +H_FILES = krpc.h nfs.h nfsdiskless.h nfsproto.h rpcv2.h xdr_subs.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs $(H_FILES:%=$(PROJECT_INCLUDE)/nfs/%) + +$(PROJECT_INCLUDE)/nfs: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/nfs/%.h: %.h + $(INSTALL_DATA) $< $@ + include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/rtems/Makefile.am b/c/src/exec/libnetworking/rtems/Makefile.am index 28df4629c4..dfcac20c4b 100644 --- a/c/src/exec/libnetworking/rtems/Makefile.am +++ b/c/src/exec/libnetworking/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -15,6 +15,19 @@ C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) OBJS = $(C_O_FILES) +H_FILES = rtems_bsdnet.h rtems_bsdnet_internal.h tftp.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems $(H_FILES:%=$(PROJECT_INCLUDE)/rtems/%) + +$(PROJECT_INCLUDE)/rtems: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/rtems/%.h: %.h + $(INSTALL_DATA) $< $@ + + include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../automake/lib.am @@ -28,14 +41,12 @@ AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ $(LIB): $(OBJS) $(make-library) -all-local: $(ARCH) $(OBJS) $(LIB) +all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) .PRECIOUS: $(LIB) -EXTRA_DIST = issetugid.c rtems_bootp.c rtems_bsdnet.h \ - rtems_bsdnet_internal.h rtems_glue.c rtems_select.c rtems_showicmpstat.c \ +EXTRA_DIST = issetugid.c rtems_bootp.c rtems_glue.c rtems_select.c rtems_showicmpstat.c \ rtems_showifstat.c rtems_showipstat.c rtems_showmbuf.c rtems_showroute.c \ - rtems_showtcpstat.c rtems_showudpstat.c rtems_syscall.c sghostname.c \ - tftp.h + rtems_showtcpstat.c rtems_showudpstat.c rtems_syscall.c sghostname.c include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/rtems/rtems_syscall.c b/c/src/exec/libnetworking/rtems/rtems_syscall.c index 05217f7212..d04ae95afb 100644 --- a/c/src/exec/libnetworking/rtems/rtems_syscall.c +++ b/c/src/exec/libnetworking/rtems/rtems_syscall.c @@ -136,11 +136,8 @@ connect (int s, struct sockaddr *name, int namelen) return -1; } error = soconnect (so, nam); - if (error) { - errno = error; - rtems_bsdnet_semaphore_release (); - return -1; - } + if (error) + goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { m_freem(nam); errno = EINPROGRESS; @@ -148,15 +145,20 @@ connect (int s, struct sockaddr *name, int namelen) return -1; } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - so->so_error = soconnsleep (so); + error = soconnsleep (so); + if (error) + break; } if (error == 0) { error = so->so_error; so->so_error = 0; } + bad: so->so_state &= ~SS_ISCONNECTING; m_freem (nam); - if (error == 0) + if (error) + errno = error; + else ret = 0; rtems_bsdnet_semaphore_release (); return ret; @@ -605,6 +607,7 @@ getpeersockname (int s, struct sockaddr *name, int *namelen, int pflag) else error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m); if (error) { + m_freem(m); errno = error; rtems_bsdnet_semaphore_release (); return -1; diff --git a/c/src/exec/libnetworking/sys/Makefile.am b/c/src/exec/libnetworking/sys/Makefile.am index 3fe88aff59..07888ddcc7 100644 --- a/c/src/exec/libnetworking/sys/Makefile.am +++ b/c/src/exec/libnetworking/sys/Makefile.am @@ -4,10 +4,22 @@ AUTOMAKE_OPTIONS = foreign 1.4 -EXTRA_DIST = buf.h callout.h cdefs.h conf.h domain.h filio.h ioccom.h \ +H_FILES = buf.h callout.h cdefs.h conf.h domain.h filio.h ioccom.h \ ioctl.h kernel.h libkern.h malloc.h mbuf.h mount.h param.h proc.h \ protosw.h queue.h reboot.h resourcevar.h rtprio.h select.h signalvar.h \ socket.h socketvar.h sockio.h sysctl.h syslimits.h syslog.h systm.h \ - ttycom.h ttydefaults.h ucred.h uio.h + ttycom.h ttydefaults.h ucred.h uio.h un.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys $(H_FILES:%=$(PROJECT_INCLUDE)/sys/%) + +$(PROJECT_INCLUDE)/sys: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/sys/%.h: %.h + $(INSTALL_DATA) $< $@ + +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/sys/un.h b/c/src/exec/libnetworking/sys/un.h index e69de29bb2..d742bb7d5d 100644 --- a/c/src/exec/libnetworking/sys/un.h +++ b/c/src/exec/libnetworking/sys/un.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1982, 1986, 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. + * + * @(#)un.h 8.3 (Berkeley) 2/19/95 + * $FreeBSD: src/sys/sys/un.h,v 1.17 1999/12/29 04:24:49 peter Exp $ + */ + +#ifndef _SYS_UN_H_ +#define _SYS_UN_H_ + +/* + * Definitions for UNIX IPC domain. + */ +struct sockaddr_un { + u_char sun_len; /* sockaddr len including null */ + u_char sun_family; /* AF_UNIX */ + char sun_path[104]; /* path name (gag) */ +}; + +#ifdef _KERNEL +struct mbuf; +struct socket; + +int uipc_usrreq __P((struct socket *so, int req, struct mbuf *m, + struct mbuf *nam, struct mbuf *control)); +int unp_connect2 __P((struct socket *so, struct socket *so2)); +void unp_dispose __P((struct mbuf *m)); +int unp_externalize __P((struct mbuf *rights)); +void unp_init __P((void)); +extern struct pr_usrreqs uipc_usrreqs; +#else /* !_KERNEL */ + +/* actual length of an initialized sockaddr_un */ +#define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + +#endif /* _KERNEL */ + +#endif /* !_SYS_UN_H_ */ diff --git a/c/src/exec/libnetworking/vm/Makefile.am b/c/src/exec/libnetworking/vm/Makefile.am index 3f307c7cfb..b72458f6cc 100644 --- a/c/src/exec/libnetworking/vm/Makefile.am +++ b/c/src/exec/libnetworking/vm/Makefile.am @@ -1,9 +1,22 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 -EXTRA_DIST = vm.h vm_extern.h vm_kern.h vm_param.h +H_FILES = vm.h vm_extern.h vm_kern.h vm_param.h + +noinst_HEADERS = $(H_FILES) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/vm \ + $(H_FILES:%=$(PROJECT_INCLUDE)/vm/%) + +$(PROJECT_INCLUDE)/vm: + @$(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/vm/%.h: %.h + $(INSTALL_DATA) $< $@ + +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/libnetworking/wrapup/Makefile.am b/c/src/exec/libnetworking/wrapup/Makefile.am index 5d2a73a05e..5553252d11 100644 --- a/c/src/exec/libnetworking/wrapup/Makefile.am +++ b/c/src/exec/libnetworking/wrapup/Makefile.am @@ -1,12 +1,12 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 if HAS_POSIX POSIX_PIECES = rtems_webserver -endif +endif NET_O_PIECES = kern lib libc net netinet nfs rtems rtems_servers pppd \ $(POSIX_PIECES) diff --git a/c/src/exec/librpc/Makefile.am b/c/src/exec/librpc/Makefile.am index e74c9e748c..d9429399ec 100644 --- a/c/src/exec/librpc/Makefile.am +++ b/c/src/exec/librpc/Makefile.am @@ -7,5 +7,7 @@ ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal SUBDIRS = include src +EXTRA_DIST = README_RTEMS + include $(top_srcdir)/../../../automake/subdirs.am include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/README_RTEMS b/c/src/exec/librpc/README_RTEMS index e69de29bb2..e60f8799aa 100644 --- a/c/src/exec/librpc/README_RTEMS +++ b/c/src/exec/librpc/README_RTEMS @@ -0,0 +1,64 @@ +USING RPC/XDR ON RTEMS +====================== +For the most part, programmers using RPC/XDR routines on RTEMS +can proceed as if they were to be using a POSIX/UNIX system. +The only significant changes are those to start the portmapper +and to allow use of RPC/XDR by multiple threads. + +Starting the portmapper +======================= +The SUN portmapper program has been modified to run as an RTEMS +task. Applications which need the portmapper can start this +task by calling: + int rtems_rpc_start_portmapper (int priority); +The return value is an RTEMS status code. + +Multi-threaded operation +======================== +The RPC/XDR package has been modified to allow for multiple RTEMS +tasks to use RPC/XDR routines. If more than one task is to call +an RPC/XDR routine, the additional tasks must call: + int rtems_rpc_task_init(void); +before calling any RPC/XDR routines. For example, the portmapper +calls this routine since the portmapper uses RPC/XDR routines in +a separate thread. +The return value is an RTEMS status code. + + +Porting Notes +============= +Most of the FreeBSD rpc library ports to RTEMS with little +or no modification beyond that required to provide for operation +in a multitasking environment. Multitasking operation was +provided by moving all `static persistence' variables into +a single structure and using an RTEMS task variable to point +to that structure. + +Some of the library, however, has not made it into the RTEMS +implementation. FreeBSD source files which have been left out include: +- Files which provide RPC to the AF_UNIX address family: + clnt_unix.c + svc_unix.c + An `ifndef __rtems__' was added to clnt_generic.c because clnt_unix.c + was omitted. +- Files which need NIS: + auth_time.c +- Files which provide DES authentication: + auth_des.c + authdes_prot.c + crypt_client.c + des_crypt.c + des_soft.c + getpublickey.c + key_call.c + key_prot_xdr.c + svc_auth_des.c + +The FreeBSD xdr source compiles and runs on RTEMS without modification. + +The original source was obtained from: + ftp://ftp.FreeBSD.org/pub/FreeBSD/ + branches/4.0-stable/src/lib/libc/rpc + branches/4.0-stable/src/lib/libc/xdr + branches/4.0-stable/src/include/rpc + branches/4.0-stable/src/include/rpcsvc diff --git a/c/src/exec/librpc/include/Makefile.am b/c/src/exec/librpc/include/Makefile.am index d5385c1f70..bb33b0a8b6 100644 --- a/c/src/exec/librpc/include/Makefile.am +++ b/c/src/exec/librpc/include/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 -SUBDIRS = rpc +SUBDIRS = rpc rpcsvc include $(top_srcdir)/../../../automake/subdirs.am include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/include/rpc/Makefile.am b/c/src/exec/librpc/include/rpc/Makefile.am index 5ca801b3c9..a917bd86dc 100644 --- a/c/src/exec/librpc/include/rpc/Makefile.am +++ b/c/src/exec/librpc/include/rpc/Makefile.am @@ -4,14 +4,15 @@ AUTOMAKE_OPTIONS = foreign 1.4 -H_FILES = auth.h rpc.h svc.h types.h clnt.h rpc_msg.h svc_auth.h xdr.h +H_FILES = auth.h auth_des.h auth_unix.h clnt.h des.h des_crypt.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 noinst_HEADERS = $(H_FILES) if HAS_NETWORKING -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rpc \ -$(H_FILES:%=$(PROJECT_INCLUDE)/rpc/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc \ + $(H_FILES:%=$(PROJECT_INCLUDE)/rpc/%) $(PROJECT_INCLUDE)/rpc: @$(mkinstalldirs) $@ @@ -19,8 +20,6 @@ $(PROJECT_INCLUDE)/rpc/%.h: %.h $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/include/rpc/auth.h b/c/src/exec/librpc/include/rpc/auth.h index 8f14d144f6..a15be39185 100644 --- a/c/src/exec/librpc/include/rpc/auth.h +++ b/c/src/exec/librpc/include/rpc/auth.h @@ -1,7 +1,3 @@ -#ifndef RPC_AUTH_H -#define RPC_AUTH_H - -/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -9,26 +5,30 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ /* @@ -41,6 +41,10 @@ * "sessions". */ +#ifndef _RPC_AUTH_H +#define _RPC_AUTH_H +#include +#include #define MAX_AUTH_BYTES 400 #define MAXNETNAMELEN 255 /* maximum length of network user's name */ @@ -67,13 +71,15 @@ enum auth_stat { union des_block { struct { - u_int32 high; - u_int32 low; + u_int32_t high; + u_int32_t low; } key; char c[8]; }; typedef union des_block des_block; -extern bool_t xdr_des_block(); +__BEGIN_DECLS +extern bool_t xdr_des_block __P((XDR *, des_block *)); +__END_DECLS /* * Authentication info. Opaque to client. @@ -83,21 +89,29 @@ struct opaque_auth { caddr_t oa_base; /* address of more auth stuff */ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ }; +__BEGIN_DECLS +bool_t xdr_opaque_auth __P((XDR *xdrs, struct opaque_auth *ap)); +__END_DECLS /* * Auth handle, interface to client side authenticators. */ -typedef struct { +typedef struct __rpc_auth { struct opaque_auth ah_cred; struct opaque_auth ah_verf; union des_block ah_key; struct auth_ops { - void (*ah_nextverf)(); - int (*ah_marshal)(); /* nextverf & serialize */ - int (*ah_validate)(); /* validate varifier */ - int (*ah_refresh)(); /* refresh credentials */ - void (*ah_destroy)(); /* destroy this structure */ + void (*ah_nextverf) __P((struct __rpc_auth *)); + /* nextverf & serialize */ + int (*ah_marshal) __P((struct __rpc_auth *, XDR *)); + /* validate verifier */ + int (*ah_validate) __P((struct __rpc_auth *, + struct opaque_auth *)); + /* refresh credentials */ + int (*ah_refresh) __P((struct __rpc_auth *)); + /* destroy this structure */ + void (*ah_destroy) __P((struct __rpc_auth *)); } *ah_ops; caddr_t ah_private; } AUTH; @@ -139,7 +153,6 @@ typedef struct { extern struct opaque_auth _null_auth; - /* * These are the various implementations of client side authenticators. */ @@ -153,15 +166,95 @@ extern struct opaque_auth _null_auth; * int len; * int *aup_gids; */ -extern AUTH *authunix_create(); -extern AUTH *authunix_create_default(); /* takes no parameters */ -extern AUTH *authnone_create(); /* takes no parameters */ -extern AUTH *authdes_create(); +__BEGIN_DECLS +struct sockaddr_in; +extern AUTH *authunix_create __P((char *, int, int, int, int *)); +extern AUTH *authunix_create_default __P((void)); +extern AUTH *authnone_create __P((void)); +__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) + * char *servername; - network name of server + * u_int window; - time to live + * struct sockaddr *timehost; - optional hostname to sync with + * des_block *ckey; - optional conversation key to use + */ +__BEGIN_DECLS +extern AUTH *authdes_create __P(( char *, u_int, struct sockaddr *, des_block * )); +#ifdef NOTYET +/* + * TI-RPC supports this call, but it requires the inclusion of + * NIS+-specific headers which would require the inclusion of other + * headers which would result in a tangled mess. For now, the NIS+ + * code prototypes this routine internally. + */ +extern AUTH *authdes_pk_create __P(( char *, netobj *, u_int, + struct sockaddr *, des_block *, + nis_server * )); +#endif +__END_DECLS + +/* + * Netname manipulation routines. + */ +__BEGIN_DECLS +extern int netname2user __P(( char *, uid_t *, gid_t *, int *, gid_t *)); +extern int netname2host __P(( char *, char *, int )); +extern int getnetname __P(( char * )); +extern int user2netname __P(( char *, uid_t, char * )); +extern int host2netname __P(( char *, char *, char * )); +extern void passwd2des __P(( char *, char * )); +__END_DECLS + +/* + * Keyserv interface routines. + * XXX Should not be here. + */ +#ifndef HEXKEYBYTES +#define HEXKEYBYTES 48 +#endif +typedef char kbuf[HEXKEYBYTES]; +typedef char *namestr; + +struct netstarg { + kbuf st_priv_key; + kbuf st_pub_key; + namestr st_netname; +}; + +__BEGIN_DECLS +extern int key_decryptsession __P(( const char *, des_block * )); +extern int key_decryptsession_pk __P(( char *, netobj *, des_block * )); +extern int key_encryptsession __P(( const char *, des_block * )); +extern int key_encryptsession_pk __P(( char *, netobj *, des_block * )); +extern int key_gendes __P(( des_block * )); +extern int key_setsecret __P(( const char * )); +extern int key_secretkey_is_set __P(( void )); +extern int key_setnet __P(( struct netstarg * )); +extern int key_get_conv __P(( char *, des_block * )); +__END_DECLS + +/* + * Publickey routines. + */ +__BEGIN_DECLS +extern int getpublickey __P(( char *, char * )); +extern int getpublicandprivatekey __P(( char *, char * )); +extern int getsecretkey __P(( char *, char *, char * )); +__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_SHORT 2 /* short hand unix style */ #define AUTH_DES 3 /* des style (encrypted timestamps) */ -#endif /* RPC_AUTH_H */ +#endif /* !_RPC_AUTH_H */ diff --git a/c/src/exec/librpc/include/rpc/auth_des.h b/c/src/exec/librpc/include/rpc/auth_des.h index e69de29bb2..a7635f87e1 100644 --- a/c/src/exec/librpc/include/rpc/auth_des.h +++ b/c/src/exec/librpc/include/rpc/auth_des.h @@ -0,0 +1,109 @@ +/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */ +/* + * 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. + */ + +/* + * auth_des.h, Protocol for DES style authentication for RPC + */ + +#ifndef _AUTH_DES_ +#define _AUTH_DES_ + +/* + * There are two kinds of "names": fullnames and nicknames + */ +enum authdes_namekind { + ADN_FULLNAME, + ADN_NICKNAME +}; + +/* + * A fullname contains the network name of the client, + * a conversation key and the window + */ +struct authdes_fullname { + char *name; /* network name of client, up to MAXNETNAMELEN */ + des_block key; /* conversation key */ + u_long window; /* associated window */ +}; + + +/* + * A credential + */ +struct authdes_cred { + enum authdes_namekind adc_namekind; + struct authdes_fullname adc_fullname; + u_long adc_nickname; +}; + + + +/* + * A des authentication verifier + */ +struct authdes_verf { + union { + struct timeval adv_ctime; /* clear time */ + des_block adv_xtime; /* crypt time */ + } adv_time_u; + u_long adv_int_u; +}; + +/* + * des authentication verifier: client variety + * + * adv_timestamp is the current time. + * adv_winverf is the credential window + 1. + * Both are encrypted using the conversation key. + */ +#define adv_timestamp adv_time_u.adv_ctime +#define adv_xtimestamp adv_time_u.adv_xtime +#define adv_winverf adv_int_u + +/* + * des authentication verifier: server variety + * + * adv_timeverf is the client's timestamp + client's window + * adv_nickname is the server's nickname for the client. + * adv_timeverf is encrypted using the conversation key. + */ +#define adv_timeverf adv_time_u.adv_ctime +#define adv_xtimeverf adv_time_u.adv_xtime +#define adv_nickname adv_int_u + +__BEGIN_DECLS +extern int authdes_getucred __P(( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * )); +__END_DECLS + +#endif /* ndef _AUTH_DES_ */ diff --git a/c/src/exec/librpc/include/rpc/auth_unix.h b/c/src/exec/librpc/include/rpc/auth_unix.h index e69de29bb2..4b015b67ab 100644 --- a/c/src/exec/librpc/include/rpc/auth_unix.h +++ b/c/src/exec/librpc/include/rpc/auth_unix.h @@ -0,0 +1,84 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)auth_unix.h 1.8 88/02/08 SMI + * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC + * $FreeBSD: src/include/rpc/auth_unix.h,v 1.10 1999/08/27 23:45:03 peter Exp $ + */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H +#include + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms { + u_long aup_time; + char *aup_machname; + int aup_uid; + int aup_gid; + u_int aup_len; + int *aup_gids; +}; + +#define authsys_parms authunix_parms + +__BEGIN_DECLS +extern bool_t xdr_authunix_parms __P((XDR *, struct authunix_parms *)); +__END_DECLS + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf { + struct opaque_auth new_cred; +}; + +#endif /* !_RPC_AUTH_UNIX_H */ diff --git a/c/src/exec/librpc/include/rpc/clnt.h b/c/src/exec/librpc/include/rpc/clnt.h index faefdb5d50..dc0f12d25c 100644 --- a/c/src/exec/librpc/include/rpc/clnt.h +++ b/c/src/exec/librpc/include/rpc/clnt.h @@ -1,7 +1,3 @@ -#ifndef RPC_CLNT_H -#define RPC_CLNT_H - -/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -9,26 +5,30 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * from: @(#)clnt.h 1.31 88/02/08 SMI + * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC + * $FreeBSD: src/include/rpc/clnt.h,v 1.11 1999/08/27 23:45:03 peter Exp $ */ /* @@ -37,8 +37,10 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef _CLNT_ -#define _CLNT_ +#ifndef _RPC_CLNT_H_ +#define _RPC_CLNT_H_ +#include +#include /* * Rpc calls return an enum clnt_stat. This should be looked at more, @@ -90,15 +92,15 @@ enum clnt_stat { struct rpc_err { enum clnt_stat re_status; union { - int RE_errno; /* realated system error */ + int RE_errno; /* related system error */ enum auth_stat RE_why; /* why the auth error occurred */ struct { - u_long low; /* lowest verion supported */ - u_long high; /* highest verion supported */ + u_int32_t low; /* lowest verion supported */ + u_int32_t high; /* highest verion supported */ } RE_vers; struct { /* maybe meaningful if RPC_FAILED */ - long s1; - long s2; + int32_t s1; + int32_t s2; } RE_lb; /* life boot & debugging only */ } ru; #define re_errno ru.RE_errno @@ -113,15 +115,26 @@ struct rpc_err { * Created by individual implementations, see e.g. rpc_udp.c. * Client is responsible for initializing auth, see e.g. auth_none.c. */ -typedef struct { +typedef struct __rpc_client { 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 */ + /* call remote procedure */ + enum clnt_stat (*cl_call) __P((struct __rpc_client *, + u_long, xdrproc_t, caddr_t, xdrproc_t, + caddr_t, struct timeval)); + /* abort a call */ + void (*cl_abort) __P((struct __rpc_client *)); + /* get specific error code */ + void (*cl_geterr) __P((struct __rpc_client *, + struct rpc_err *)); + /* frees results */ + bool_t (*cl_freeres) __P((struct __rpc_client *, + xdrproc_t, caddr_t)); + /* destroy this structure */ + void (*cl_destroy) __P((struct __rpc_client *)); + /* the ioctl() of rpc */ + bool_t (*cl_control) __P((struct __rpc_client *, u_int, + void *)); } *cl_ops; caddr_t cl_private; /* private stuff */ } CLIENT; @@ -146,9 +159,11 @@ typedef struct { * struct timeval timeout; */ #define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ - ((*(rh)->cl_ops->cl_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)) + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \ + xres, (caddr_t)resp, secs)) /* * void @@ -188,17 +203,42 @@ typedef struct { #define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) /* - * control operations that apply to both udp and tcp transports + * 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. + * */ #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_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ #define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ +/* + * Operations which GSSAPI needs. (Bletch.) + */ +#define CLGET_LOCAL_ADDR 19 /* get local addr (sockaddr) */ + + /* * void * CLNT_DESTROY(rh); @@ -209,7 +249,7 @@ typedef struct { /* - * RPCTEST is a test program which is accessable on every rpc + * RPCTEST is a test program which is accessible on every rpc * transport/port. It is used for testing, performance evaluation, * and network administration. */ @@ -227,7 +267,7 @@ typedef struct { /* * Below are the client handle creation routines for the various - * implementations of client side rpc. They can return NULL if a + * implementations of client side rpc. They can return NULL if a * creation failure occurs. */ @@ -238,21 +278,24 @@ typedef struct { * u_long prog; * u_long vers; */ -extern CLIENT *clntraw_create(); +__BEGIN_DECLS +extern CLIENT *clntraw_create __P((u_long, u_long)); +__END_DECLS /* - * Generic client creation routine. Supported protocols are "udp" and "tcp" + * Generic client creation routine. Supported protocols are "udp", "tcp" + * and "unix". + * CLIENT * + * clnt_create(host, prog, vers, prot); + * char *host; -- hostname + * u_long prog; -- program number + * u_long vers; -- version number + * char *prot; -- protocol */ -extern CLIENT * -clnt_create(/*host, prog, vers, prot*/); /* - char *host; -- hostname - u_long prog; -- program number - u_long vers; -- version number - char *prot; -- protocol -*/ - - +__BEGIN_DECLS +extern CLIENT *clnt_create __P((char *, u_long, u_long, char *)); +__END_DECLS /* @@ -266,7 +309,15 @@ clnt_create(/*host, prog, vers, prot*/); /* * u_int sendsz; * u_int recvsz; */ -extern CLIENT *clnttcp_create(); +__BEGIN_DECLS +extern CLIENT *clnttcp_create __P((struct sockaddr_in *, + u_long, + u_long, + int *, + u_int, + u_int)); +__END_DECLS + /* * UDP based rpc. @@ -289,27 +340,69 @@ extern CLIENT *clnttcp_create(); * u_int sendsz; * u_int recvsz; */ -extern CLIENT *clntudp_create(); -extern CLIENT *clntudp_bufcreate(); +__BEGIN_DECLS +extern CLIENT *clntudp_create __P((struct sockaddr_in *, + u_long, + u_long, + struct timeval, + int *)); +extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, + u_long, + u_long, + struct timeval, + int *, + u_int, + u_int)); +__END_DECLS + + +/* + * AF_UNIX based rpc + * CLIENT * + * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_un *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +__BEGIN_DECLS +extern CLIENT *clntunix_create __P((struct sockaddr_un *, + u_long, + u_long, + int *, + u_int, + u_int)); +__END_DECLS + /* * Print why creation failed */ -void clnt_pcreateerror(/* char *msg */); /* stderr */ -char *clnt_spcreateerror(/* char *msg */); /* string */ +__BEGIN_DECLS +extern void clnt_pcreateerror __P((char *)); /* stderr */ +extern char *clnt_spcreateerror __P((char *)); /* string */ +__END_DECLS /* * Like clnt_perror(), but is more verbose in its output - */ -void clnt_perrno(/* enum clnt_stat num */); /* stderr */ + */ +__BEGIN_DECLS +extern void clnt_perrno __P((enum clnt_stat)); /* stderr */ +extern char *clnt_sperrno __P((enum clnt_stat)); /* string */ +__END_DECLS /* * Print an English error message, given the client error code */ -void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */ -char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */ +__BEGIN_DECLS +extern void clnt_perror __P((CLIENT *, char *)); /* stderr */ +extern char *clnt_sperror __P((CLIENT *, char *)); /* string */ +__END_DECLS -/* + +/* * If a creation fails, the following allows the user to figure out why. */ struct rpc_createerr { @@ -320,17 +413,7 @@ struct rpc_createerr { extern struct rpc_createerr rpc_createerr; - -/* - * Copy error message to buffer. - */ -char *clnt_sperrno(/* enum clnt_stat num */); /* string */ - - - #define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ #define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ -#endif /*!_CLNT_*/ - -#endif /* RPC_CLNT_H */ +#endif /* !_RPC_CLNT_H */ diff --git a/c/src/exec/librpc/include/rpc/des.h b/c/src/exec/librpc/include/rpc/des.h index e69de29bb2..f41e5a7804 100644 --- a/c/src/exec/librpc/include/rpc/des.h +++ b/c/src/exec/librpc/include/rpc/des.h @@ -0,0 +1,82 @@ +/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ +/* + * 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 + */ +/* + * Generic DES driver interface + * Keep this file hardware independent! + * Copyright (c) 1986 by Sun Microsystems, Inc. + */ + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +enum desdir { ENCRYPT, DECRYPT }; +enum desmode { CBC, ECB }; + +/* + * parameters to ioctl call + */ +struct desparams { + u_char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + u_char des_ivec[8]; /* input vector */ + unsigned des_len; /* number of bytes to crypt */ + union { + u_char UDES_data[DES_QUICKLEN]; + u_char *UDES_buf; + } UDES; +# define des_data UDES.UDES_data /* direct data here if quick */ +# define des_buf UDES.UDES_buf /* otherwise, pointer to data */ +}; + +#ifdef notdef + +/* + * These ioctls are only implemented in SunOS. Maybe someday + * if somebody writes a driver for DES hardware that works + * with FreeBSD, we can being that back. + */ + +/* + * Encrypt an arbitrary sized buffer + */ +#define DESIOCBLOCK _IOWR(d, 6, struct desparams) + +/* + * Encrypt of small amount of data, quickly + */ +#define DESIOCQUICK _IOWR(d, 7, struct desparams) + +#endif + +/* + * Software DES. + */ +extern int _des_crypt __P(( char *, int, struct desparams * )); diff --git a/c/src/exec/librpc/include/rpc/des_crypt.h b/c/src/exec/librpc/include/rpc/des_crypt.h index e69de29bb2..c9458fcf24 100644 --- a/c/src/exec/librpc/include/rpc/des_crypt.h +++ b/c/src/exec/librpc/include/rpc/des_crypt.h @@ -0,0 +1,120 @@ +/* + * @(#)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 $ + * + * des_crypt.h, des library routine interface + * Copyright (C) 1986, Sun Microsystems, Inc. + */ +/* + * 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 + +#define DES_MAXDATA 8192 /* max bytes encrypted in one call */ +#define DES_DIRMASK (1 << 0) +#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ +#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ + + +#define DES_DEVMASK (1 << 1) +#define DES_HW (0*DES_DEVMASK) /* Use hardware device */ +#define DES_SW (1*DES_DEVMASK) /* Use software device */ + + +#define DESERR_NONE 0 /* succeeded */ +#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ +#define DESERR_HWERROR 2 /* failed, hardware/driver error */ +#define DESERR_BADPARAM 3 /* failed, bad parameter to call */ + +#define DES_FAILED(err) \ + ((err) > DESERR_NOHWDEVICE) + +/* + * cbc_crypt() + * ecb_crypt() + * + * Encrypt (or decrypt) len bytes of a buffer buf. + * The length must be a multiple of eight. + * The key should have odd parity in the low bit of each byte. + * ivec is the input vector, and is updated to the new one (cbc only). + * The mode is created by oring together the appropriate parameters. + * DESERR_NOHWDEVICE is returned if DES_HW was specified but + * there was no hardware to do it on (the data will still be + * encrypted though, in software). + */ + + +/* + * Cipher Block Chaining mode + */ +__BEGIN_DECLS +#ifdef __STDC__ +int cbc_crypt __P(( char *, char *, unsigned int, unsigned int, char *)); +#else +cbc_crypt(/* key, buf, len, mode, ivec */); /* + char *key; + char *buf; + unsigned len; + unsigned mode; + char *ivec; +*/ +#endif + +/* + * Electronic Code Book mode + */ +#ifdef __STDC__ +int ecb_crypt __P(( char *, char *, unsigned int, unsigned int )); +#else +ecb_crypt(/* key, buf, len, mode */); /* + char *key; + char *buf; + unsigned len; + unsigned mode; +*/ +#endif +__END_DECLS + +#ifndef _KERNEL +/* + * Set des parity for a key. + * DES parity is odd and in the low bit of each byte + */ +__BEGIN_DECLS +#ifdef __STDC__ +void des_setparity __P(( char *)); +#else +void +des_setparity(/* key */); /* + char *key; +*/ +#endif +__END_DECLS +#endif diff --git a/c/src/exec/librpc/include/rpc/pmap_clnt.h b/c/src/exec/librpc/include/rpc/pmap_clnt.h index e69de29bb2..2f4a2780dd 100644 --- a/c/src/exec/librpc/include/rpc/pmap_clnt.h +++ b/c/src/exec/librpc/include/rpc/pmap_clnt.h @@ -0,0 +1,85 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * 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 $ + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +#ifndef _RPC_PMAPCLNT_H +#define _RPC_PMAPCLNT_H +#include + +__BEGIN_DECLS +extern bool_t pmap_set __P((u_long, u_long, int, int)); +extern bool_t pmap_unset __P((u_long, u_long)); +extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *)); +extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *, + u_long, u_long, u_long, + xdrproc_t, caddr_t, + xdrproc_t, caddr_t, + struct timeval, u_long *)); +extern enum clnt_stat clnt_broadcast __P((u_long, u_long, u_long, + xdrproc_t, char *, + xdrproc_t, char *, + bool_t (*) __P((caddr_t, + struct sockaddr_in *)))); +extern u_short pmap_getport __P((struct sockaddr_in *, + u_long, u_long, u_int)); +__END_DECLS + +#endif /* !_RPC_PMAPCLNT_H */ diff --git a/c/src/exec/librpc/include/rpc/pmap_prot.h b/c/src/exec/librpc/include/rpc/pmap_prot.h index e69de29bb2..14f0837bfe 100644 --- a/c/src/exec/librpc/include/rpc/pmap_prot.h +++ b/c/src/exec/librpc/include/rpc/pmap_prot.h @@ -0,0 +1,104 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * 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 $ + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#ifndef _RPC_PMAPPROT_H +#define _RPC_PMAPPROT_H +#include + +#define PMAPPORT ((u_short)111) +#define PMAPPROG ((u_long)100000) +#define PMAPVERS ((u_long)2) +#define PMAPVERS_PROTO ((u_long)2) +#define PMAPVERS_ORIG ((u_long)1) +#define PMAPPROC_NULL ((u_long)0) +#define PMAPPROC_SET ((u_long)1) +#define PMAPPROC_UNSET ((u_long)2) +#define PMAPPROC_GETPORT ((u_long)3) +#define PMAPPROC_DUMP ((u_long)4) +#define PMAPPROC_CALLIT ((u_long)5) + +struct pmap { + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +}; + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +__BEGIN_DECLS +extern bool_t xdr_pmap __P((XDR *, struct pmap *)); +extern bool_t xdr_pmaplist __P((XDR *, struct pmaplist **)); +__END_DECLS + +#endif /* !_RPC_PMAPPROT_H */ diff --git a/c/src/exec/librpc/include/rpc/pmap_rmt.h b/c/src/exec/librpc/include/rpc/pmap_rmt.h index e69de29bb2..e632f8deca 100644 --- a/c/src/exec/librpc/include/rpc/pmap_rmt.h +++ b/c/src/exec/librpc/include/rpc/pmap_rmt.h @@ -0,0 +1,63 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * 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 $ + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAPRMT_H +#define _RPC_PMAPRMT_H +#include + +struct rmtcallargs { + u_long prog, vers, proc, arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +struct rmtcallres { + u_long *port_ptr; + u_long resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +__BEGIN_DECLS +extern bool_t xdr_rmtcall_args __P((XDR *, struct rmtcallargs *)); +extern bool_t xdr_rmtcallres __P((XDR *, struct rmtcallres *)); +__END_DECLS + +#endif /* !_RPC_PMAPRMT_H */ diff --git a/c/src/exec/librpc/include/rpc/rpc.h b/c/src/exec/librpc/include/rpc/rpc.h index 0a0affd82a..f68dc1be89 100644 --- a/c/src/exec/librpc/include/rpc/rpc.h +++ b/c/src/exec/librpc/include/rpc/rpc.h @@ -1,7 +1,3 @@ -#ifndef RPC_H -#define RPC_H - -/* @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -9,11 +5,11 @@ * 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 + * 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. @@ -29,6 +25,10 @@ * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ /* @@ -37,12 +37,11 @@ * * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef __RPC_HEADER__ -#define __RPC_HEADER__ +#ifndef _RPC_RPC_H +#define _RPC_RPC_H #include /* some typedefs */ #include -#include /* external data representation interfaces */ #include /* generic (de)serializer */ @@ -55,12 +54,12 @@ /* semi-private protocol headers */ #include /* protocol for rpc messages */ -/*#include "auth_unix.h" * protocol for unix style cred */ +#include /* protocol for unix style cred */ /* - * Uncomment-out the next line if you are building the rpc library with + * Uncomment-out the next line if you are building the rpc library with * DES Authentication (see the README file in the secure_rpc/ directory). */ -/*#include "auth_des.h" * protocol for des style cred */ +#include /* protocol for des style cred */ /* Server side only remote procedure callee */ #include /* service manager and multiplexer */ @@ -79,8 +78,60 @@ struct rpcent { int r_number; /* rpc program number */ }; -struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); +__BEGIN_DECLS +extern struct rpcent *getrpcbyname __P((char *)); +extern struct rpcent *getrpcbynumber __P((int)); +extern struct rpcent *getrpcent __P((void)); +extern int getrpcport __P((char *host, int prognum, int versnum, int proto)); +extern void setrpcent __P((int)); +extern void endrpcent __P((void)); + +extern int bindresvport __P((int, struct sockaddr_in *)); +extern int bindresvport_sa __P((int, struct sockaddr *)); +extern int get_myaddress __P((struct sockaddr_in *)); +__END_DECLS + +int rtems_rpc_task_init (void); +int rtems_rpc_start_portmapper (int priority); + +#ifdef _RTEMS_RPC_INTERNAL_ +/* + * Multi-threaded support + * Group all global and static variables into a single spot. + * This area will be allocated on a per-task basis + */ +struct rtems_rpc_task_variables { + int svc_svc_maxfd; + fd_set svc_svc_fdset; + void *svc_xports; + int svc_xportssize; + int svc__svc_fdsetsize; + void *svc__svc_fdset; + void *svc_svc_head; + + void *clnt_perror_buf; + + void *clnt_raw_private; + + void *call_rpc_private; + + void *svc_raw_private; + + void *svc_simple_proglst; + void *svc_simple_pl; + void *svc_simple_transp; + + void *rpcdname_default_domain; + + void *svc_auths_Auths; +}; +extern void *rtems_rpc_task_variables; + +#define svc_maxfd (((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_svc_maxfd) +#define svc_fdset (((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_svc_fdset) +#define __svc_fdsetsize (((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc__svc_fdsetsize) +#define __svc_fdset (fd_set *)(((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc__svc_fdset) -#endif /* ndef __RPC_HEADER__ */ +#endif /* _RTEMS_RPC_INTERNAL_ */ -#endif /* RPC_H */ +#endif /* !_RPC_RPC_H */ diff --git a/c/src/exec/librpc/include/rpc/rpc_com.h b/c/src/exec/librpc/include/rpc/rpc_com.h index e69de29bb2..2cf5995d2d 100644 --- a/c/src/exec/librpc/include/rpc/rpc_com.h +++ b/c/src/exec/librpc/include/rpc/rpc_com.h @@ -0,0 +1,78 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. + */ + +/* + * rpc_com.h, Common definitions for both the server and client side. + * All for the topmost layer of rpc + * + */ + +#ifndef _RPC_RPCCOM_H +#define _RPC_RPCCOM_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 + +#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 + +#ifdef __cplusplus +} +#endif + +#endif /* _RPC_RPCCOM_H */ diff --git a/c/src/exec/librpc/include/rpc/rpc_msg.h b/c/src/exec/librpc/include/rpc/rpc_msg.h index 2f34fb614c..bc5dc223fd 100644 --- a/c/src/exec/librpc/include/rpc/rpc_msg.h +++ b/c/src/exec/librpc/include/rpc/rpc_msg.h @@ -1,7 +1,3 @@ -#ifndef RPC_MSG_H -#define RPC_MSG_H - -/* @(#)rpc_msg.h 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 @@ -9,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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ -/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ /* * rpc_msg.h @@ -39,6 +38,9 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ +#ifndef _RPC_RPCMSG_H +#define _RPC_RPCMSG_H + #define RPC_MSG_VERSION ((u_long) 2) #define RPC_SERVICE_PORT ((u_short) 2048) @@ -86,8 +88,8 @@ struct accepted_reply { enum accept_stat ar_stat; union { struct { - u_long low; - u_long high; + u_int32_t low; + u_int32_t high; } AR_versions; struct { caddr_t where; @@ -106,8 +108,8 @@ struct rejected_reply { enum reject_stat rj_stat; union { struct { - u_long low; - u_long high; + u_int32_t low; + u_int32_t high; } RJ_versions; enum auth_stat RJ_why; /* why authentication did not work */ } ru; @@ -132,10 +134,10 @@ struct reply_body { * Body of an rpc request call. */ struct call_body { - u_long cb_rpcvers; /* must be equal to two */ - u_long cb_prog; - u_long cb_vers; - u_long cb_proc; + 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; struct opaque_auth cb_cred; struct opaque_auth cb_verf; /* protocol specific - provided by client */ }; @@ -144,7 +146,7 @@ struct call_body { * The rpc message */ struct rpc_msg { - u_long rm_xid; + u_int32_t rm_xid; enum msg_type rm_direction; union { struct call_body RM_cmb; @@ -156,14 +158,14 @@ struct rpc_msg { #define acpted_rply ru.RM_rmb.ru.RP_ar #define rjcted_rply ru.RM_rmb.ru.RP_dr - +__BEGIN_DECLS /* * XDR routine to handle a rpc message. * xdr_callmsg(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ -extern bool_t xdr_callmsg(); +extern bool_t xdr_callmsg __P((XDR *, struct rpc_msg *)); /* * XDR routine to pre-serialize the static part of a rpc message. @@ -171,7 +173,7 @@ extern bool_t xdr_callmsg(); * XDR *xdrs; * struct rpc_msg *cmsg; */ -extern bool_t xdr_callhdr(); +extern bool_t xdr_callhdr __P((XDR *, struct rpc_msg *)); /* * XDR routine to handle a rpc reply. @@ -179,7 +181,7 @@ extern bool_t xdr_callhdr(); * XDR *xdrs; * struct rpc_msg *rmsg; */ -extern bool_t xdr_replymsg(); +extern bool_t xdr_replymsg __P((XDR *, struct rpc_msg *)); /* * Fills in the error part of a reply message. @@ -187,6 +189,8 @@ extern bool_t xdr_replymsg(); * struct rpc_msg *msg; * struct rpc_err *error; */ -extern void _seterr_reply(); +struct rpc_err; +extern void _seterr_reply __P((struct rpc_msg *, struct rpc_err *)); +__END_DECLS -#endif /* RPC_MSG_H */ +#endif /* !_RPC_RPCMSG_H */ diff --git a/c/src/exec/librpc/include/rpc/svc.h b/c/src/exec/librpc/include/rpc/svc.h index c576b5538b..e57a7454be 100644 --- a/c/src/exec/librpc/include/rpc/svc.h +++ b/c/src/exec/librpc/include/rpc/svc.h @@ -1,8 +1,3 @@ - -#ifndef RPC_SVC_H -#define RPC_SVC_H - -/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -10,26 +5,30 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ /* @@ -38,8 +37,9 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef __SVC_HEADER__ -#define __SVC_HEADER__ +#ifndef _RPC_SVC_H +#define _RPC_SVC_H +#include /* * This interface must manage two items concerning remote procedure calling: @@ -69,19 +69,31 @@ enum xprt_stat { XPRT_IDLE }; +struct rpc_msg; + /* * Server side transport handle */ -typedef struct { +typedef struct __rpc_svcxprt { int xp_sock; u_short xp_port; /* associated port number */ struct xp_ops { - bool_t (*xp_recv)(); /* receive incomming 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 */ + /* receive incoming requests */ + bool_t (*xp_recv) __P((struct __rpc_svcxprt *, + struct rpc_msg *)); + /* get transport status */ + enum xprt_stat (*xp_stat) __P((struct __rpc_svcxprt *)); + /* get arguments */ + bool_t (*xp_getargs) __P((struct __rpc_svcxprt *, xdrproc_t, + caddr_t)); + /* send reply */ + bool_t (*xp_reply) __P((struct __rpc_svcxprt *, + struct rpc_msg *)); + /* free mem allocated for args */ + bool_t (*xp_freeargs) __P((struct __rpc_svcxprt *, xdrproc_t, + caddr_t)); + /* destroy this struct */ + void (*xp_destroy) __P((struct __rpc_svcxprt *)); } *xp_ops; int xp_addrlen; /* length of remote address */ struct sockaddr_in xp_raddr; /* remote address */ @@ -138,9 +150,9 @@ typedef struct { * Service request */ struct svc_req { - u_long rq_prog; /* service program number */ - u_long rq_vers; /* service protocol version */ - u_long rq_proc; /* the desired procedure */ + 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 */ @@ -155,9 +167,12 @@ struct svc_req { * u_long prog; * u_long vers; * void (*dispatch)(); - * int protocol; (like TCP or UDP, zero means do not register) + * int protocol; (like TCP or UDP, zero means do not register) */ -extern bool_t svc_register(); +__BEGIN_DECLS +extern bool_t svc_register __P((SVCXPRT *, u_long, u_long, + void (*) __P((struct svc_req *, SVCXPRT *)), int)); +__END_DECLS /* * Service un-registration @@ -166,7 +181,9 @@ extern bool_t svc_register(); * u_long prog; * u_long vers; */ -extern void svc_unregister(); +__BEGIN_DECLS +extern void svc_unregister __P((u_long, u_long)); +__END_DECLS /* * Transport registration. @@ -174,7 +191,9 @@ extern void svc_unregister(); * xprt_register(xprt) * SVCXPRT *xprt; */ -extern void xprt_register(); +__BEGIN_DECLS +extern void xprt_register __P((SVCXPRT *)); +__END_DECLS /* * Transport un-register @@ -182,7 +201,9 @@ extern void xprt_register(); * xprt_unregister(xprt) * SVCXPRT *xprt; */ -extern void xprt_unregister(); +__BEGIN_DECLS +extern void xprt_unregister __P((SVCXPRT *)); +__END_DECLS @@ -190,7 +211,7 @@ extern void xprt_unregister(); /* * 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 - * and return. If so, it should deserialize its arguments via + * and return. If so, it should deserialize its arguments via * SVC_GETARGS (defined above). If the deserialization does not work, * svcerr_decode should be called followed by a return. Successful * decoding of the arguments should be followed the execution of the @@ -201,7 +222,7 @@ extern void xprt_unregister(); * Note: do not confuse access-control failure with weak authentication! * * NB: In pure implementations of rpc, the caller always waits for a reply - * msg. This message is sent when svc_sendreply is called. + * msg. This message is sent when svc_sendreply is called. * Therefore pure service implementations should always call * svc_sendreply even if the function logically returns void; use * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows @@ -213,15 +234,17 @@ extern void xprt_unregister(); * deadlock the caller and server processes! */ -extern bool_t svc_sendreply(); -extern void svcerr_decode(); -extern void svcerr_weakauth(); -extern void svcerr_noproc(); -extern void svcerr_progvers(); -extern void svcerr_auth(); -extern void svcerr_noprog(); -extern void svcerr_systemerr(); - +__BEGIN_DECLS +extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *)); +extern void svcerr_decode __P((SVCXPRT *)); +extern void svcerr_weakauth __P((SVCXPRT *)); +extern void svcerr_noproc __P((SVCXPRT *)); +extern void svcerr_progvers __P((SVCXPRT *, u_long, u_long)); +extern void svcerr_auth __P((SVCXPRT *, enum auth_stat)); +extern void svcerr_noprog __P((SVCXPRT *)); +extern void svcerr_systemerr __P((SVCXPRT *)); +__END_DECLS + /* * Lowest level dispatching -OR- who owns this process anyway. * Somebody has to wait for incoming requests and then call the correct @@ -235,24 +258,26 @@ extern void svcerr_systemerr(); /* * Global keeper of rpc service descriptors in use - * dynamic; must be inspected before each call to select + * dynamic; must be inspected before each call to select */ -#ifdef FD_SETSIZE +extern int svc_maxfd; 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 -extern void svc_getreq(); -extern void svc_getreqset(); /* takes fdset instead of int */ -extern void svc_run(); /* never returns */ +__BEGIN_DECLS +extern void svc_getreq __P((int)); +extern void svc_getreqset __P((fd_set *)); +extern void svc_getreqset2 __P((fd_set *, int)); /* XXX: nonstd, undoc */ +extern void svc_run __P((void)); +__END_DECLS /* * Socket to use on svcxxx_create call to get default socket @@ -266,26 +291,34 @@ extern void svc_run(); /* never returns */ /* * Memory based rpc for testing and timing. */ -extern SVCXPRT *svcraw_create(); +__BEGIN_DECLS +extern SVCXPRT *svcraw_create __P((void)); +__END_DECLS + /* * Udp based rpc. */ -extern SVCXPRT *svcudp_create(); -extern SVCXPRT *svcudp_bufcreate(); -extern int svcudp_enablecache(SVCXPRT *transp, u_long size); +__BEGIN_DECLS +extern SVCXPRT *svcudp_create __P((int)); +extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int)); +__END_DECLS + /* * Tcp based rpc. */ -extern SVCXPRT *svctcp_create(); - +__BEGIN_DECLS +extern SVCXPRT *svctcp_create __P((int, u_int, u_int)); +extern SVCXPRT *svcfd_create __P((int, u_int, u_int)); +__END_DECLS +/* + * AF_UNIX socket based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcunix_create __P((int, u_int, u_int, char *)); +extern SVCXPRT *svcunixfd_create __P((int, u_int, u_int)); +__END_DECLS -#endif /* !__SVC_HEADER__ */ - -extern int _rpcsvccount; -extern int _rpcsvcstate; -extern int _SERVED; - -#endif /* RPC_SVC_H */ +#endif /* !_RPC_SVC_H */ diff --git a/c/src/exec/librpc/include/rpc/svc_auth.h b/c/src/exec/librpc/include/rpc/svc_auth.h index 5c233a6a47..a203d8cbeb 100644 --- a/c/src/exec/librpc/include/rpc/svc_auth.h +++ b/c/src/exec/librpc/include/rpc/svc_auth.h @@ -1,7 +1,3 @@ -#ifndef RPC_SVC_AUTH_H -#define RPC_SVC_AUTH_H - -/* @(#)svc_auth.h 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 @@ -9,39 +5,52 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ -/* @(#)svc_auth.h 1.6 86/07/16 SMI */ /* * svc_auth.h, Service side of rpc authentication. - * + * * Copyright (C) 1984, Sun Microsystems, Inc. */ +#ifndef _RPC_SVCAUTH_H +#define _RPC_SVCAUTH_H + +struct rpc_msg; +struct svc_req; /* * Server side authenticator */ -extern enum auth_stat _authenticate(); +__BEGIN_DECLS +extern enum auth_stat _authenticate __P((struct svc_req *, struct rpc_msg *)); +extern int svc_auth_reg __P((int, enum auth_stat (*)(struct svc_req *, + struct rpc_msg *))); +extern enum auth_stat _svcauth_des __P((struct svc_req *, struct rpc_msg *)); +__END_DECLS -#endif /* SVC_AUTH_H */ +#endif /* !_RPC_SVCAUTH_H */ diff --git a/c/src/exec/librpc/include/rpc/types.h b/c/src/exec/librpc/include/rpc/types.h index b6d7eb3ccc..c907674c51 100644 --- a/c/src/exec/librpc/include/rpc/types.h +++ b/c/src/exec/librpc/include/rpc/types.h @@ -1,7 +1,3 @@ -#ifndef RPC_TYPES_H -#define RPC_TYPES_H - -/* @(#)types.h 2.3 88/08/15 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 @@ -9,52 +5,52 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 $ */ -/* @(#)types.h 1.18 87/07/24 SMI */ /* * Rpc additions to */ -#ifndef __TYPES_RPC_HEADER__ -#define __TYPES_RPC_HEADER__ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H -/*#include */ -typedef unsigned long u_int32; /* 32-bit unsigned integers */ +#define bool_t int32_t +#define enum_t int32_t +#define __dontcare__ -1 -#define bool_t int -#define enum_t int #ifndef FALSE -# define FALSE (0) +# define FALSE (0) #endif #ifndef TRUE -# define TRUE (1) +# define TRUE (1) #endif -#define __dontcare__ -1 #ifndef NULL -# define NULL 0 +# define NULL 0 #endif -void *malloc(); #define mem_alloc(bsize) malloc(bsize) #define mem_free(ptr, bsize) free(ptr) @@ -63,13 +59,4 @@ void *malloc(); #endif #include -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK (u_long)0x7F000001 -#endif -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#endif /* ndef __TYPES_RPC_HEADER__ */ - -#endif /* RPC_TYPES_H */ +#endif /* !_RPC_TYPES_H */ diff --git a/c/src/exec/librpc/include/rpc/xdr.h b/c/src/exec/librpc/include/rpc/xdr.h index ef2df51d93..460a1da5fb 100644 --- a/c/src/exec/librpc/include/rpc/xdr.h +++ b/c/src/exec/librpc/include/rpc/xdr.h @@ -1,7 +1,3 @@ -#ifndef RPC_XDR_H -#define RPC_XDR_H - -/* @(#)xdr.h 2.2 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 @@ -9,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 + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * + * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. - * + * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. - * + * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. - * + * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 + * + * 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 1999/12/29 05:00:44 peter Exp $ */ -/* @(#)xdr.h 1.19 87/04/22 SMI */ /* * xdr.h, External Data Representation Serialization Routines. @@ -38,8 +37,9 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#ifndef __XDR_HEADER__ -#define __XDR_HEADER__ +#ifndef _RPC_XDR_H +#define _RPC_XDR_H +#include /* * XDR provides a conventional way for converting between C data @@ -89,34 +89,31 @@ enum xdr_op { #define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ * 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 pointer is 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 paticular implementation (e.g. see xdr_mem.c), - * and two private fields for the use of the particular impelementation. + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. */ -typedef struct { +typedef struct __rpc_xdr { 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 " */ - bool_t (*x_getbytes)();/* get some bytes from " */ - bool_t (*x_putbytes)();/* put some bytes to " */ - 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 */ + /* get a long from underlying stream */ + bool_t (*x_getlong) __P((struct __rpc_xdr *, long *)); + /* put a long to underlying stream */ + bool_t (*x_putlong) __P((struct __rpc_xdr *, long *)); + /* get some bytes from underlying stream */ + bool_t (*x_getbytes) __P((struct __rpc_xdr *, caddr_t, u_int)); + /* put some bytes to underlying stream */ + bool_t (*x_putbytes) __P((struct __rpc_xdr *, caddr_t, u_int)); + /* returns bytes off from beginning */ + u_int (*x_getpostn) __P((struct __rpc_xdr *)); + /* lets you reposition the stream */ + bool_t (*x_setpostn) __P((struct __rpc_xdr *, u_int)); + /* buf quick ptr to buffered data */ + int32_t *(*x_inline) __P((struct __rpc_xdr *, u_int)); + /* free privates of this xdr_stream */ + void (*x_destroy) __P((struct __rpc_xdr *)); } *x_ops; caddr_t x_public; /* users' data */ caddr_t x_private; /* pointer to private data */ @@ -124,6 +121,23 @@ typedef struct { int x_handy; /* extra private word */ } XDR; +/* + * 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 pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + */ +#ifdef _KERNEL +typedef bool_t (*xdrproc_t) __P((XDR *, void *, u_int)); +#else +/* + * XXX can't actually prototype it, because some take two args!!! + */ +typedef bool_t (*xdrproc_t) __P((/* XDR *, void *, u_int */)); +#endif + /* * Operations defined on a XDR handle * @@ -192,7 +206,7 @@ struct xdr_discrim { }; /* - * In-line routines for fast encode/decode of primitve data types. + * In-line routines for fast encode/decode of primitive data types. * Caveat emptor: these use single memory cycles to get the * data from the underlying buffer, and will fail to operate * properly if the data is not aligned. The standard way to use these @@ -224,52 +238,77 @@ struct xdr_discrim { /* * These are the "generic" xdr routines. */ -extern bool_t xdr_void(); -extern bool_t xdr_int(); -extern bool_t xdr_u_int(); -extern bool_t xdr_long(); -extern bool_t xdr_u_long(); -extern bool_t xdr_short(); -extern bool_t xdr_u_short(); -extern bool_t xdr_bool(); -extern bool_t xdr_enum(); -extern bool_t xdr_array(); -extern bool_t xdr_bytes(); -extern bool_t xdr_opaque(); -extern bool_t xdr_string(); -extern bool_t xdr_union(); -extern bool_t xdr_char(); -extern bool_t xdr_u_char(); -extern bool_t xdr_vector(); -extern bool_t xdr_float(); -extern bool_t xdr_double(); -extern bool_t xdr_reference(); -extern bool_t xdr_pointer(); -extern bool_t xdr_wrapstring(); +__BEGIN_DECLS +extern bool_t xdr_void __P((void)); +extern bool_t xdr_int __P((XDR *, int *)); +extern bool_t xdr_u_int __P((XDR *, u_int *)); +extern bool_t xdr_long __P((XDR *, long *)); +extern bool_t xdr_u_long __P((XDR *, u_long *)); +extern bool_t xdr_short __P((XDR *, short *)); +extern bool_t xdr_u_short __P((XDR *, u_short *)); +extern bool_t xdr_int16_t __P((XDR *, int16_t *)); +extern bool_t xdr_u_int16_t __P((XDR *, u_int16_t *)); +extern bool_t xdr_int32_t __P((XDR *, int32_t *)); +extern bool_t xdr_u_int32_t __P((XDR *, u_int32_t *)); +extern bool_t xdr_int64_t __P((XDR *, int64_t *)); +extern bool_t xdr_u_int64_t __P((XDR *, u_int64_t *)); +extern bool_t xdr_bool __P((XDR *, bool_t *)); +extern bool_t xdr_enum __P((XDR *, enum_t *)); +extern bool_t xdr_array __P((XDR *, char **, u_int *, u_int, u_int, xdrproc_t)); +extern bool_t xdr_bytes __P((XDR *, char **, u_int *, u_int)); +extern bool_t xdr_opaque __P((XDR *, caddr_t, u_int)); +extern bool_t xdr_string __P((XDR *, char **, u_int)); +extern bool_t xdr_union __P((XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t)); +extern unsigned long xdr_sizeof __P((xdrproc_t, void *)); +extern bool_t xdr_char __P((XDR *, char *)); +extern bool_t xdr_u_char __P((XDR *, u_char *)); +extern bool_t xdr_vector __P((XDR *, char *, u_int, u_int, xdrproc_t)); +extern bool_t xdr_float __P((XDR *, float *)); +extern bool_t xdr_double __P((XDR *, double *)); +extern bool_t xdr_reference __P((XDR *, caddr_t *, u_int, xdrproc_t)); +extern bool_t xdr_pointer __P((XDR *, caddr_t *, u_int, xdrproc_t)); +extern bool_t xdr_wrapstring __P((XDR *, char **)); +extern void xdr_free __P((xdrproc_t, char *)); +__END_DECLS /* * Common opaque bytes objects used by many rpc protocols; * declared here due to commonality. */ -#define MAX_NETOBJ_SZ 1024 +#define MAX_NETOBJ_SZ 1024 struct netobj { u_int n_len; char *n_bytes; }; typedef struct netobj netobj; -extern bool_t xdr_netobj(); +extern bool_t xdr_netobj __P((XDR *, struct netobj *)); /* * These are the public routines for the various implementations of * xdr streams. */ -extern void xdrmem_create(); /* XDR using memory buffers */ -extern void xdrstdio_create(); /* XDR using stdio library */ -extern void xdrrec_create(); /* XDR pseudo records for tcp */ -extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ -extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ -extern bool_t xdrrec_eof(); /* true if no more input */ +__BEGIN_DECLS +/* XDR using memory buffers */ +extern void xdrmem_create __P((XDR *, char *, u_int, enum xdr_op)); + +#ifdef _STDIO_H_ +/* XDR using stdio library */ +extern void xdrstdio_create __P((XDR *, FILE *, enum xdr_op)); +#endif + +/* XDR pseudo records for tcp */ +extern void xdrrec_create __P((XDR *, u_int, u_int, char *, + int (*) __P((caddr_t, caddr_t, int)), + int (*) __P((caddr_t, caddr_t, int)))); + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord __P((XDR *, int)); + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord __P((XDR *)); -#endif /* !__XDR_HEADER__ */ +/* true if no more input */ +extern bool_t xdrrec_eof __P((XDR *)); +__END_DECLS -#endif /* RPC_XDR_H */ +#endif /* !_RPC_XDR_H */ diff --git a/c/src/exec/librpc/include/rpcsvc/.cvsignore b/c/src/exec/librpc/include/rpcsvc/.cvsignore index e69de29bb2..282522db03 100644 --- a/c/src/exec/librpc/include/rpcsvc/.cvsignore +++ b/c/src/exec/librpc/include/rpcsvc/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/exec/librpc/include/rpcsvc/Makefile.am b/c/src/exec/librpc/include/rpcsvc/Makefile.am index e69de29bb2..c5de0f9e6f 100644 --- a/c/src/exec/librpc/include/rpcsvc/Makefile.am +++ b/c/src/exec/librpc/include/rpcsvc/Makefile.am @@ -0,0 +1,13 @@ +## $Id$ + +AUTOMAKE_OPTIONS = foreign 1.4 + +## Currently unused + +EXTRA_DIST = bootparam_prot.x crypt.x key_prot.x klm_prot.x mount.x \ + nfs_prot.x nis.x nis_cache.x nis_callback.x nis_db.h nis_object.x \ + nis_tags.h nislib.h nlm_prot.x pmap_prot.x rex.x rnusers.x rquota.x \ + rstat.x rwall.x sm_inter.x spray.x yp.x yp_prot.h ypclnt.h yppasswd.x \ + ypupdate_prot.x ypxfrd.x + +include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/include/rpcsvc/bootparam_prot.x b/c/src/exec/librpc/include/rpcsvc/bootparam_prot.x index e69de29bb2..0f74c8f8ad 100644 --- a/c/src/exec/librpc/include/rpcsvc/bootparam_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/bootparam_prot.x @@ -0,0 +1,103 @@ +/* + * 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 for bootparms service. + * There are two procedures: + * WHOAMI takes a net address and returns a client name and also a + * likely net address for routing + * GETFILE takes a client name and file identifier and returns the + * server name, server net address and pathname for the file. + * file identifiers typically include root, swap, pub and dump + */ + +#ifdef RPC_HDR +%#include +%#include +%#include +%#include +%#include +%#include +#else +%#ifndef lint +%/*static char sccsid[] = "from: @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/bootparam_prot.x,v 1.5 1999/08/27 23:45:07 peter Exp $"; +%#endif /* not lint */ +#endif + +const MAX_MACHINE_NAME = 255; +const MAX_PATH_LEN = 1024; +const MAX_FILEID = 32; +const IP_ADDR_TYPE = 1; + +typedef string bp_machine_name_t; +typedef string bp_path_t; +typedef string bp_fileid_t; + +struct ip_addr_t { + char net; + char host; + char lh; + char impno; +}; + +union bp_address switch (int address_type) { + case IP_ADDR_TYPE: + ip_addr_t ip_addr; +}; + +struct bp_whoami_arg { + bp_address client_address; +}; + +struct bp_whoami_res { + bp_machine_name_t client_name; + bp_machine_name_t domain_name; + bp_address router_address; +}; + +struct bp_getfile_arg { + bp_machine_name_t client_name; + bp_fileid_t file_id; +}; + +struct bp_getfile_res { + bp_machine_name_t server_name; + bp_address server_address; + bp_path_t server_path; +}; + +program BOOTPARAMPROG { + version BOOTPARAMVERS { + bp_whoami_res BOOTPARAMPROC_WHOAMI(bp_whoami_arg) = 1; + bp_getfile_res BOOTPARAMPROC_GETFILE(bp_getfile_arg) = 2; + } = 1; +} = 100026; diff --git a/c/src/exec/librpc/include/rpcsvc/crypt.x b/c/src/exec/librpc/include/rpcsvc/crypt.x index e69de29bb2..8df1654440 100644 --- a/c/src/exec/librpc/include/rpcsvc/crypt.x +++ b/c/src/exec/librpc/include/rpcsvc/crypt.x @@ -0,0 +1,91 @@ +/* + * 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/include/rpcsvc/crypt.x,v 1.3 1999/08/27 23:45:08 peter Exp $ + */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/crypt.x,v 1.3 1999/08/27 23:45:08 peter Exp $"; +%#endif +#endif + +/* + * This protocol definition exists because of the U.S. government and + * its stupid export laws. We can't export DES code from the United + * States to other countries (even though the code already exists + * outside the U.S. -- go figure that one out) but we need to make + * Secure RPC work. The normal way around this is to break the DES + * code out into a shared library; we can then provide a dummy lib + * in the base OS and provide the real lib in the secure dist, which + * the user can install later. But we need Secure RPC for NIS+, and + * there are several system programs that use NIS+ which are statically + * linked. We would have to provide replacements for these programs + * in the secure dist, but there are a lot, and this is a pain. The + * shared lib trick won't work for these programs, and we can't change + * them once they're compiled. + * + * One solution for this problem is to do the DES encryption as a system + * call; no programs need to be changed and we can even supply the DES + * support as an LKM. But this bloats the kernel. Maybe if we have + * Secure NFS one day this will be worth it, but for now we should keep + * this mess in user space. + * + * So we have this second solution: we provide a server that does the + * DES encryption for us. In this case, the server is keyserv (we need + * it to make Secure RPC work anyway) and we use this protocol to ship + * the data back and forth between keyserv and the application. + */ + +enum des_dir { ENCRYPT_DES, DECRYPT_DES }; +enum des_mode { CBC_DES, ECB_DES }; + +struct desargs { + u_char des_key[8]; /* key (with low bit parity) */ + des_dir des_dir; /* direction */ + des_mode des_mode; /* mode */ + u_char des_ivec[8]; /* input vector */ + opaque desbuf<>; +}; + +struct desresp { + opaque desbuf<>; + u_char des_ivec[8]; + int stat; +}; + +program CRYPT_PROG { + version CRYPT_VERS { + desresp + DES_CRYPT(desargs) = 1; + } = 1; +} = 600100029; diff --git a/c/src/exec/librpc/include/rpcsvc/key_prot.x b/c/src/exec/librpc/include/rpcsvc/key_prot.x index e69de29bb2..ab3196cfc0 100644 --- a/c/src/exec/librpc/include/rpcsvc/key_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/key_prot.x @@ -0,0 +1,284 @@ +%/* +% * 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 +% */ +/* + * Key server protocol definition + * Copyright (C) 1990, 1991 Sun Microsystems, Inc. + * + * The keyserver is a public key storage/encryption/decryption service + * The encryption method used is based on the Diffie-Hellman exponential + * key exchange technology. + * + * The key server is local to each machine, akin to the portmapper. + * Under TI-RPC, communication with the keyserver is through the + * loopback transport. + * + * NOTE: This .x file generates the USER level headers for the keyserver. + * the KERNEL level headers are created by hand as they kernel has special + * requirements. + */ + +%/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */ +% +%/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ +% +%/* +% * Compiled from key_prot.x using rpcgen. +% * DO NOT EDIT THIS FILE! +% * This is NOT source code! +% */ + +/* + * PROOT and MODULUS define the way the Diffie-Hellman key is generated. + * + * MODULUS should be chosen as a prime of the form: MODULUS == 2*p + 1, + * where p is also prime. + * + * PROOT satisfies the following two conditions: + * (1) (PROOT ** 2) % MODULUS != 1 + * (2) (PROOT ** p) % MODULUS != 1 + * + */ + +const PROOT = 3; +const HEXMODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; + +const HEXKEYBYTES = 48; /* HEXKEYBYTES == strlen(HEXMODULUS) */ +const KEYSIZE = 192; /* KEYSIZE == bit length of key */ +const KEYBYTES = 24; /* byte length of key */ + +/* + * The first 16 hex digits of the encrypted secret key are used as + * a checksum in the database. + */ +const KEYCHECKSUMSIZE = 16; + +/* + * status of operation + */ +enum keystatus { + KEY_SUCCESS, /* no problems */ + KEY_NOSECRET, /* no secret key stored */ + KEY_UNKNOWN, /* unknown netname */ + KEY_SYSTEMERR /* system error (out of memory, encryption failure) */ +}; + +typedef opaque keybuf[HEXKEYBYTES]; /* store key in hex */ + +typedef string netnamestr; + +/* + * Argument to ENCRYPT or DECRYPT + */ +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; + +/* + * Argument to ENCRYPT_PK or DECRYPT_PK + */ +struct cryptkeyarg2 { + netnamestr remotename; + netobj remotekey; /* Contains a length up to 1024 bytes */ + des_block deskey; +}; + + +/* + * Result of ENCRYPT, DECRYPT, ENCRYPT_PK, and DECRYPT_PK + */ +union cryptkeyres switch (keystatus status) { +case KEY_SUCCESS: + des_block deskey; +default: + void; +}; + +const MAXGIDS = 16; /* max number of gids in gid list */ + +/* + * Unix credential + */ +struct unixcred { + u_int uid; + u_int gid; + u_int gids; +}; + +/* + * Result returned from GETCRED + */ +union getcredres switch (keystatus status) { +case KEY_SUCCESS: + unixcred cred; +default: + void; +}; +/* + * key_netstarg; + */ + +struct key_netstarg { + keybuf st_priv_key; + keybuf st_pub_key; + netnamestr st_netname; +}; + +union key_netstres switch (keystatus status){ +case KEY_SUCCESS: + key_netstarg knet; +default: + void; +}; + +#ifdef RPC_HDR +% +%#ifndef opaque +%#define opaque char +%#endif +% +#endif +program KEY_PROG { + version KEY_VERS { + + /* + * This is my secret key. + * Store it for me. + */ + keystatus + KEY_SET(keybuf) = 1; + + /* + * I want to talk to X. + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT(cryptkeyarg) = 2; + + /* + * X just sent me a message. + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT(cryptkeyarg) = 3; + + /* + * Generate a secure conversation key for me + */ + des_block + KEY_GEN(void) = 4; + + /* + * Get me the uid, gid and group-access-list associated + * with this netname (for kernel which cannot use NIS) + */ + getcredres + KEY_GETCRED(netnamestr) = 5; + } = 1; + version KEY_VERS2 { + + /* + * ####### + * Procedures 1-5 are identical to version 1 + * ####### + */ + + /* + * This is my secret key. + * Store it for me. + */ + keystatus + KEY_SET(keybuf) = 1; + + /* + * I want to talk to X. + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT(cryptkeyarg) = 2; + + /* + * X just sent me a message. + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT(cryptkeyarg) = 3; + + /* + * Generate a secure conversation key for me + */ + des_block + KEY_GEN(void) = 4; + + /* + * Get me the uid, gid and group-access-list associated + * with this netname (for kernel which cannot use NIS) + */ + getcredres + KEY_GETCRED(netnamestr) = 5; + + /* + * I want to talk to X. and I know X's public key + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT_PK(cryptkeyarg2) = 6; + + /* + * X just sent me a message. and I know X's public key + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT_PK(cryptkeyarg2) = 7; + + /* + * Store my public key, netname and private key. + */ + keystatus + KEY_NET_PUT(key_netstarg) = 8; + + /* + * Retrieve my public key, netname and private key. + */ + key_netstres + KEY_NET_GET(void) = 9; + + /* + * Return me the conversation key that is constructed + * from my secret key and this publickey. + */ + + cryptkeyres + KEY_GET_CONV(keybuf) = 10; + + + } = 2; +} = 100029; + + diff --git a/c/src/exec/librpc/include/rpcsvc/klm_prot.x b/c/src/exec/librpc/include/rpcsvc/klm_prot.x index e69de29bb2..c4cfe36d42 100644 --- a/c/src/exec/librpc/include/rpcsvc/klm_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/klm_prot.x @@ -0,0 +1,139 @@ +/* + * 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 + */ + +/* + * Kernel/lock manager protocol definition + * Copyright (C) 1986 Sun Microsystems, Inc. + * + * protocol used between the UNIX kernel (the "client") and the + * local lock manager. The local lock manager is a deamon running + * above the kernel. + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)klm_prot.x 1.7 87/07/08 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)klm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/klm_prot.x,v 1.6 1999/08/27 23:45:08 peter Exp $"; +%#endif /* not lint */ +#endif + +const LM_MAXSTRLEN = 1024; + +/* + * lock manager status returns + */ +enum klm_stats { + klm_granted = 0, /* lock is granted */ + klm_denied = 1, /* lock is denied */ + klm_denied_nolocks = 2, /* no lock entry available */ + klm_working = 3 /* lock is being processed */ +}; + +/* + * lock manager lock identifier + */ +struct klm_lock { + string server_name; + netobj fh; /* a counted file handle */ + int pid; /* holder of the lock */ + unsigned l_offset; /* beginning offset of the lock */ + unsigned l_len; /* byte length of the lock; + * zero means through end of file */ +}; + +/* + * lock holder identifier + */ +struct klm_holder { + bool exclusive; /* FALSE if shared lock */ + int svid; /* holder of the lock (pid) */ + unsigned l_offset; /* beginning offset of the lock */ + unsigned l_len; /* byte length of the lock; + * zero means through end of file */ +}; + +/* + * reply to KLM_LOCK / KLM_UNLOCK / KLM_CANCEL + */ +struct klm_stat { + klm_stats stat; +}; + +/* + * reply to a KLM_TEST call + */ +union klm_testrply switch (klm_stats stat) { + case klm_denied: + struct klm_holder holder; + default: /* All other cases return no arguments */ + void; +}; + + +/* + * arguments to KLM_LOCK + */ +struct klm_lockargs { + bool block; + bool exclusive; + struct klm_lock alock; +}; + +/* + * arguments to KLM_TEST + */ +struct klm_testargs { + bool exclusive; + struct klm_lock alock; +}; + +/* + * arguments to KLM_UNLOCK + */ +struct klm_unlockargs { + struct klm_lock alock; +}; + +program KLM_PROG { + version KLM_VERS { + + klm_testrply KLM_TEST (struct klm_testargs) = 1; + + klm_stat KLM_LOCK (struct klm_lockargs) = 2; + + klm_stat KLM_CANCEL (struct klm_lockargs) = 3; + /* klm_granted=> the cancel request fails due to lock is already granted */ + /* klm_denied=> the cancel request successfully aborts +lock request */ + + klm_stat KLM_UNLOCK (struct klm_unlockargs) = 4; + } = 1; +} = 100020; diff --git a/c/src/exec/librpc/include/rpcsvc/mount.x b/c/src/exec/librpc/include/rpcsvc/mount.x index e69de29bb2..f68a06fe9b 100644 --- a/c/src/exec/librpc/include/rpcsvc/mount.x +++ b/c/src/exec/librpc/include/rpcsvc/mount.x @@ -0,0 +1,257 @@ +/* + * 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 + */ + +/* + * Protocol description for the mount program + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)mount.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/mount.x,v 1.6 1999/08/27 23:45:08 peter Exp $"; +%#endif /* not lint */ +#endif + +const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ +const MNTNAMLEN = 255; /* maximum bytes in a name argument */ +const FHSIZE = 32; /* size in bytes of a file handle */ +#ifdef WANT_NFS3 +const FHSIZE3 = 64; /* size in bytes of a file handle (v3) */ +#endif + +/* + * The fhandle is the file handle that the server passes to the client. + * All file operations are done using the file handles to refer to a file + * or a directory. The file handle can contain whatever information the + * server needs to distinguish an individual file. + */ +typedef opaque fhandle[FHSIZE]; +#ifdef WANT_NFS3 +typedef opaque fhandle3; +#endif + +/* + * If a status of zero is returned, the call completed successfully, and + * a file handle for the directory follows. A non-zero status indicates + * some sort of error. The status corresponds with UNIX error numbers. + */ +union fhstatus switch (unsigned fhs_status) { +case 0: + fhandle fhs_fhandle; +default: + void; +}; + +#ifdef WANT_NFS3 +/* + * Status codes returned by the version 3 mount call. + */ +enum mountstat3 { + MNT3_OK = 0, /* no error */ + MNT3ERR_PERM = 1, /* Not owner */ + MNT3ERR_NOENT = 2, /* No such file or directory */ + MNT3ERR_IO = 5, /* I/O error */ + MNT3ERR_ACCES = 13, /* Permission denied */ + MNT3ERR_NOTDIR = 20, /* Not a directory */ + MNT3ERR_INVAL = 22, /* Invalid argument */ + MNT3ERR_NAMETOOLONG = 63, /* Filename too long */ + MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ + MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */ +}; + +struct mountres3_ok { + fhandle3 fhandle; + int auth_flavors<>; +}; + +union mountres3 switch (mountstat3 fhs_status) { +case 0: + mountres3_ok mountinfo; +default: + void; +}; +#endif + +/* + * The type dirpath is the pathname of a directory + */ +typedef string dirpath; + +/* + * The type name is used for arbitrary names (hostnames, groupnames) + */ +typedef string name; + +/* + * A list of who has what mounted + */ +typedef struct mountbody *mountlist; +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; + +/* + * A list of netgroups + */ +typedef struct groupnode *groups; +struct groupnode { + name gr_name; + groups gr_next; +}; + +/* + * A list of what is exported and to whom + */ +typedef struct exportnode *exports; +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; + +program MOUNTPROG { + /* + * Version one of the mount protocol communicates with version two + * of the NFS protocol. Version three communicates with + * version three of the NFS protocol. The only connecting + * point is the fhandle structure, which is the same for both + * protocols. + */ + version MOUNTVERS { + /* + * Does no work. It is made available in all RPC services + * to allow server reponse testing and timing + */ + void + MOUNTPROC_NULL(void) = 0; + + /* + * If fhs_status is 0, then fhs_fhandle contains the + * file handle for the directory. This file handle may + * be used in the NFS protocol. This procedure also adds + * a new entry to the mount list for this client mounting + * the directory. + * Unix authentication required. + */ + fhstatus + MOUNTPROC_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC_EXPORT(void) = 5; + + /* + * Identical to MOUNTPROC_EXPORT above + */ + exports + MOUNTPROC_EXPORTALL(void) = 6; + } = 1; +#ifdef WANT_NFS3 + version MOUNTVERS3 { + /* + * Does no work. It is made available in all RPC services + * to allow server reponse testing and timing + */ + void + MOUNTPROC_NULL(void) = 0; + + /* + * If mountres3.fhs_status is MNT3_OK, then + * mountres3.mountinfo contains the file handle for + * the directory and a list of acceptable + * authentication flavors. This file handle may only + * be used in the NFS version 3 protocol. This + * procedure also results in the server adding a new + * entry to its mount list recording that this client + * has mounted the directory. AUTH_UNIX authentication + * or better is required. + */ + mountres3 + MOUNTPROC_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC_EXPORT(void) = 5; + } = 3; +#endif +} = 100005; diff --git a/c/src/exec/librpc/include/rpcsvc/nfs_prot.x b/c/src/exec/librpc/include/rpcsvc/nfs_prot.x index e69de29bb2..01564f895e 100644 --- a/c/src/exec/librpc/include/rpcsvc/nfs_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/nfs_prot.x @@ -0,0 +1,1266 @@ +/* + * 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 + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/nfs_prot.x,v 1.7 1999/08/27 23:45:08 peter Exp $"; +%#endif /* not lint */ +#endif + +const NFS_PORT = 2049; +const NFS_MAXDATA = 8192; +const NFS_MAXPATHLEN = 1024; +const NFS_MAXNAMLEN = 255; +const NFS_FHSIZE = 32; +const NFS_COOKIESIZE = 4; +const NFS_FIFO_DEV = -1; /* size kludge for named pipes */ + +/* + * File types + */ +const NFSMODE_FMT = 0170000; /* type of file */ +const NFSMODE_DIR = 0040000; /* directory */ +const NFSMODE_CHR = 0020000; /* character special */ +const NFSMODE_BLK = 0060000; /* block special */ +const NFSMODE_REG = 0100000; /* regular */ +const NFSMODE_LNK = 0120000; /* symbolic link */ +const NFSMODE_SOCK = 0140000; /* socket */ +const NFSMODE_FIFO = 0010000; /* fifo */ + +/* + * Error status + */ +enum nfsstat { + NFS_OK= 0, /* no error */ + NFSERR_PERM=1, /* Not owner */ + NFSERR_NOENT=2, /* No such file or directory */ + NFSERR_IO=5, /* I/O error */ + NFSERR_NXIO=6, /* No such device or address */ + NFSERR_ACCES=13, /* Permission denied */ + NFSERR_EXIST=17, /* File exists */ + NFSERR_NODEV=19, /* No such device */ + NFSERR_NOTDIR=20, /* Not a directory*/ + NFSERR_ISDIR=21, /* Is a directory */ + NFSERR_FBIG=27, /* File too large */ + NFSERR_NOSPC=28, /* No space left on device */ + NFSERR_ROFS=30, /* Read-only file system */ + NFSERR_NAMETOOLONG=63, /* File name too long */ + NFSERR_NOTEMPTY=66, /* Directory not empty */ + NFSERR_DQUOT=69, /* Disc quota exceeded */ + NFSERR_STALE=70, /* Stale NFS file handle */ + NFSERR_WFLUSH=99 /* write cache flushed */ +}; + +/* + * File types + */ +enum ftype { + NFNON = 0, /* non-file */ + NFREG = 1, /* regular file */ + NFDIR = 2, /* directory */ + NFBLK = 3, /* block special */ + NFCHR = 4, /* character special */ + NFLNK = 5, /* symbolic link */ + NFSOCK = 6, /* unix domain sockets */ + NFBAD = 7, /* unused */ + NFFIFO = 8 /* named pipe */ +}; + +/* + * File access handle + */ +struct nfs_fh { + opaque data[NFS_FHSIZE]; +}; + +/* + * Timeval + */ +struct nfstime { + unsigned seconds; + unsigned useconds; +}; + + +/* + * File attributes + */ +struct fattr { + ftype type; /* file type */ + unsigned mode; /* protection mode bits */ + unsigned nlink; /* # hard links */ + unsigned uid; /* owner user id */ + unsigned gid; /* owner group id */ + unsigned size; /* file size in bytes */ + unsigned blocksize; /* prefered block size */ + unsigned rdev; /* special device # */ + unsigned blocks; /* Kb of disk used by file */ + unsigned fsid; /* device # */ + unsigned fileid; /* inode # */ + nfstime atime; /* time of last access */ + nfstime mtime; /* time of last modification */ + nfstime ctime; /* time of last change */ +}; + +/* + * File attributes which can be set + */ +struct sattr { + unsigned mode; /* protection mode bits */ + unsigned uid; /* owner user id */ + unsigned gid; /* owner group id */ + unsigned size; /* file size in bytes */ + nfstime atime; /* time of last access */ + nfstime mtime; /* time of last modification */ +}; + + +typedef string filename; +typedef string nfspath; + +/* + * Reply status with file attributes + */ +union attrstat switch (nfsstat status) { +case NFS_OK: + fattr attributes; +default: + void; +}; + +struct sattrargs { + nfs_fh file; + sattr attributes; +}; + +/* + * Arguments for directory operations + */ +struct diropargs { + nfs_fh dir; /* directory file handle */ + filename name; /* name (up to NFS_MAXNAMLEN bytes) */ +}; + +struct diropokres { + nfs_fh file; + fattr attributes; +}; + +/* + * Results from directory operation + */ +union diropres switch (nfsstat status) { +case NFS_OK: + diropokres diropres; +default: + void; +}; + +union readlinkres switch (nfsstat status) { +case NFS_OK: + nfspath data; +default: + void; +}; + +/* + * Arguments to remote read + */ +struct readargs { + nfs_fh file; /* handle for file */ + unsigned offset; /* byte offset in file */ + unsigned count; /* immediate read count */ + unsigned totalcount; /* total read count (from this offset)*/ +}; + +/* + * Status OK portion of remote read reply + */ +struct readokres { + fattr attributes; /* attributes, need for pagin*/ + opaque data; +}; + +union readres switch (nfsstat status) { +case NFS_OK: + readokres reply; +default: + void; +}; + +/* + * Arguments to remote write + */ +struct writeargs { + nfs_fh file; /* handle for file */ + unsigned beginoffset; /* beginning byte offset in file */ + unsigned offset; /* current byte offset in file */ + unsigned totalcount; /* total write count (to this offset)*/ + opaque data; +}; + +struct createargs { + diropargs where; + sattr attributes; +}; + +struct renameargs { + diropargs from; + diropargs to; +}; + +struct linkargs { + nfs_fh from; + diropargs to; +}; + +struct symlinkargs { + diropargs from; + nfspath to; + sattr attributes; +}; + + +typedef opaque nfscookie[NFS_COOKIESIZE]; + +/* + * Arguments to readdir + */ +struct readdirargs { + nfs_fh dir; /* directory handle */ + nfscookie cookie; + unsigned count; /* number of directory bytes to read */ +}; + +struct entry { + unsigned fileid; + filename name; + nfscookie cookie; + entry *nextentry; +}; + +struct dirlist { + entry *entries; + bool eof; +}; + +union readdirres switch (nfsstat status) { +case NFS_OK: + dirlist reply; +default: + void; +}; + +struct statfsokres { + unsigned tsize; /* preferred transfer size in bytes */ + unsigned bsize; /* fundamental file system block size */ + unsigned blocks; /* total blocks in file system */ + unsigned bfree; /* free blocks in fs */ + unsigned bavail; /* free blocks avail to non-superuser */ +}; + +union statfsres switch (nfsstat status) { +case NFS_OK: + statfsokres reply; +default: + void; +}; + +#ifdef WANT_NFS3 + +/* + * NFSv3 constants and types + */ +const NFS3_FHSIZE = 64; /* maximum size in bytes of a file handle */ +const NFS3_COOKIEVERFSIZE = 8; /* size of a cookie verifier for READDIR */ +const NFS3_CREATEVERFSIZE = 8; /* size of the verifier used for CREATE */ +const NFS3_WRITEVERFSIZE = 8; /* size of the verifier used for WRITE */ + +typedef unsigned hyper uint64; +typedef hyper int64; +typedef unsigned long uint32; +typedef long int32; +typedef string filename3<>; +typedef string nfspath3<>; +typedef uint64 fileid3; +typedef uint64 cookie3; +typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; +typedef opaque createverf3[NFS3_CREATEVERFSIZE]; +typedef opaque writeverf3[NFS3_WRITEVERFSIZE]; +typedef uint32 uid3; +typedef uint32 gid3; +typedef uint64 size3; +typedef uint64 offset3; +typedef uint32 mode3; +typedef uint32 count3; + +/* + * Error status (v3) + */ +enum nfsstat3 { + NFS3_OK = 0, + NFS3ERR_PERM = 1, + NFS3ERR_NOENT = 2, + NFS3ERR_IO = 5, + NFS3ERR_NXIO = 6, + NFS3ERR_ACCES = 13, + NFS3ERR_EXIST = 17, + NFS3ERR_XDEV = 18, + NFS3ERR_NODEV = 19, + NFS3ERR_NOTDIR = 20, + NFS3ERR_ISDIR = 21, + NFS3ERR_INVAL = 22, + NFS3ERR_FBIG = 27, + NFS3ERR_NOSPC = 28, + NFS3ERR_ROFS = 30, + NFS3ERR_MLINK = 31, + NFS3ERR_NAMETOOLONG = 63, + NFS3ERR_NOTEMPTY = 66, + NFS3ERR_DQUOT = 69, + NFS3ERR_STALE = 70, + NFS3ERR_REMOTE = 71, + NFS3ERR_BADHANDLE = 10001, + NFS3ERR_NOT_SYNC = 10002, + NFS3ERR_BAD_COOKIE = 10003, + NFS3ERR_NOTSUPP = 10004, + NFS3ERR_TOOSMALL = 10005, + NFS3ERR_SERVERFAULT = 10006, + NFS3ERR_BADTYPE = 10007, + NFS3ERR_JUKEBOX = 10008 +}; + +/* + * File types (v3) + */ +enum ftype3 { + NF3REG = 1, /* regular file */ + NF3DIR = 2, /* directory */ + NF3BLK = 3, /* block special */ + NF3CHR = 4, /* character special */ + NF3LNK = 5, /* symbolic link */ + NF3SOCK = 6, /* unix domain sockets */ + NF3FIFO = 7 /* named pipe */ +}; + +struct specdata3 { + uint32 specdata1; + uint32 specdata2; +}; + +/* + * File access handle (v3) + */ +struct nfs_fh3 { + opaque data; +}; + +/* + * Timeval (v3) + */ +struct nfstime3 { + uint32 seconds; + uint32 nseconds; +}; + + +/* + * File attributes (v3) + */ +struct fattr3 { + ftype3 type; /* file type */ + mode3 mode; /* protection mode bits */ + uint32 nlink; /* # hard links */ + uid3 uid; /* owner user id */ + gid3 gid; /* owner group id */ + size3 size; /* file size in bytes */ + size3 used; /* prefered block size */ + specdata3 rdev; /* special device # */ + uint64 fsid; /* device # */ + fileid3 fileid; /* inode # */ + nfstime3 atime; /* time of last access */ + nfstime3 mtime; /* time of last modification */ + nfstime3 ctime; /* time of last change */ +}; + +union post_op_attr switch (bool attributes_follow) { +case TRUE: + fattr3 attributes; +case FALSE: + void; +}; + +struct wcc_attr { + size3 size; + nfstime3 mtime; + nfstime3 ctime; +}; + +union pre_op_attr switch (bool attributes_follow) { +case TRUE: + wcc_attr attributes; +case FALSE: + void; +}; + +struct wcc_data { + pre_op_attr before; + post_op_attr after; +}; + +union post_op_fh3 switch (bool handle_follows) { +case TRUE: + nfs_fh3 handle; +case FALSE: + void; +}; + +/* + * File attributes which can be set (v3) + */ +enum time_how { + DONT_CHANGE = 0, + SET_TO_SERVER_TIME = 1, + SET_TO_CLIENT_TIME = 2 +}; + +union set_mode3 switch (bool set_it) { +case TRUE: + mode3 mode; +default: + void; +}; + +union set_uid3 switch (bool set_it) { +case TRUE: + uid3 uid; +default: + void; +}; + +union set_gid3 switch (bool set_it) { +case TRUE: + gid3 gid; +default: + void; +}; + +union set_size3 switch (bool set_it) { +case TRUE: + size3 size; +default: + void; +}; + +union set_atime switch (time_how set_it) { +case SET_TO_CLIENT_TIME: + nfstime3 atime; +default: + void; +}; + +union set_mtime switch (time_how set_it) { +case SET_TO_CLIENT_TIME: + nfstime3 mtime; +default: + void; +}; + +struct sattr3 { + set_mode3 mode; + set_uid3 uid; + set_gid3 gid; + set_size3 size; + set_atime atime; + set_mtime mtime; +}; + +/* + * Arguments for directory operations (v3) + */ +struct diropargs3 { + nfs_fh3 dir; /* directory file handle */ + filename3 name; /* name (up to NFS_MAXNAMLEN bytes) */ +}; + +/* + * Arguments to getattr (v3). + */ +struct GETATTR3args { + nfs_fh3 object; +}; + +struct GETATTR3resok { + fattr3 obj_attributes; +}; + +union GETATTR3res switch (nfsstat3 status) { +case NFS3_OK: + GETATTR3resok resok; +default: + void; +}; + +/* + * Arguments to setattr (v3). + */ +union sattrguard3 switch (bool check) { +case TRUE: + nfstime3 obj_ctime; +case FALSE: + void; +}; + +struct SETATTR3args { + nfs_fh3 object; + sattr3 new_attributes; + sattrguard3 guard; +}; + +struct SETATTR3resok { + wcc_data obj_wcc; +}; + +struct SETATTR3resfail { + wcc_data obj_wcc; +}; + +union SETATTR3res switch (nfsstat3 status) { +case NFS3_OK: + SETATTR3resok resok; +default: + SETATTR3resfail resfail; +}; + +/* + * Arguments to lookup (v3). + */ +struct LOOKUP3args { + diropargs3 what; +}; + +struct LOOKUP3resok { + nfs_fh3 object; + post_op_attr obj_attributes; + post_op_attr dir_attributes; +}; + +struct LOOKUP3resfail { + post_op_attr dir_attributes; +}; + +union LOOKUP3res switch (nfsstat3 status) { +case NFS3_OK: + LOOKUP3resok resok; +default: + LOOKUP3resfail resfail; +}; + +/* + * Arguments to access (v3). + */ +const ACCESS3_READ = 0x0001; +const ACCESS3_LOOKUP = 0x0002; +const ACCESS3_MODIFY = 0x0004; +const ACCESS3_EXTEND = 0x0008; +const ACCESS3_DELETE = 0x0010; +const ACCESS3_EXECUTE = 0x0020; + +struct ACCESS3args { + nfs_fh3 object; + uint32 access; +}; + +struct ACCESS3resok { + post_op_attr obj_attributes; + uint32 access; +}; + +struct ACCESS3resfail { + post_op_attr obj_attributes; +}; + +union ACCESS3res switch (nfsstat3 status) { +case NFS3_OK: + ACCESS3resok resok; +default: + ACCESS3resfail resfail; +}; + +/* + * Arguments to readlink (v3). + */ +struct READLINK3args { + nfs_fh3 symlink; +}; + +struct READLINK3resok { + post_op_attr symlink_attributes; + nfspath3 data; +}; + +struct READLINK3resfail { + post_op_attr symlink_attributes; +}; + +union READLINK3res switch (nfsstat3 status) { +case NFS3_OK: + READLINK3resok resok; +default: + READLINK3resfail resfail; +}; + +/* + * Arguments to read (v3). + */ +struct READ3args { + nfs_fh3 file; + offset3 offset; + count3 count; +}; + +struct READ3resok { + post_op_attr file_attributes; + count3 count; + bool eof; + opaque data<>; +}; + +struct READ3resfail { + post_op_attr file_attributes; +}; + +/* XXX: solaris 2.6 uses ``nfsstat'' here */ +union READ3res switch (nfsstat3 status) { +case NFS3_OK: + READ3resok resok; +default: + READ3resfail resfail; +}; + +/* + * Arguments to write (v3). + */ +enum stable_how { + UNSTABLE = 0, + DATA_SYNC = 1, + FILE_SYNC = 2 +}; + +struct WRITE3args { + nfs_fh3 file; + offset3 offset; + count3 count; + stable_how stable; + opaque data<>; +}; + +struct WRITE3resok { + wcc_data file_wcc; + count3 count; + stable_how committed; + writeverf3 verf; +}; + +struct WRITE3resfail { + wcc_data file_wcc; +}; + +union WRITE3res switch (nfsstat3 status) { +case NFS3_OK: + WRITE3resok resok; +default: + WRITE3resfail resfail; +}; + +/* + * Arguments to create (v3). + */ +enum createmode3 { + UNCHECKED = 0, + GUARDED = 1, + EXCLUSIVE = 2 +}; + +union createhow3 switch (createmode3 mode) { +case UNCHECKED: +case GUARDED: + sattr3 obj_attributes; +case EXCLUSIVE: + createverf3 verf; +}; + +struct CREATE3args { + diropargs3 where; + createhow3 how; +}; + +struct CREATE3resok { + post_op_fh3 obj; + post_op_attr obj_attributes; + wcc_data dir_wcc; +}; + +struct CREATE3resfail { + wcc_data dir_wcc; +}; + +union CREATE3res switch (nfsstat3 status) { +case NFS3_OK: + CREATE3resok resok; +default: + CREATE3resfail resfail; +}; + +/* + * Arguments to mkdir (v3). + */ +struct MKDIR3args { + diropargs3 where; + sattr3 attributes; +}; + +struct MKDIR3resok { + post_op_fh3 obj; + post_op_attr obj_attributes; + wcc_data dir_wcc; +}; + +struct MKDIR3resfail { + wcc_data dir_wcc; +}; + +union MKDIR3res switch (nfsstat3 status) { +case NFS3_OK: + MKDIR3resok resok; +default: + MKDIR3resfail resfail; +}; + +/* + * Arguments to symlink (v3). + */ +struct symlinkdata3 { + sattr3 symlink_attributes; + nfspath3 symlink_data; +}; + +struct SYMLINK3args { + diropargs3 where; + symlinkdata3 symlink; +}; + +struct SYMLINK3resok { + post_op_fh3 obj; + post_op_attr obj_attributes; + wcc_data dir_wcc; +}; + +struct SYMLINK3resfail { + wcc_data dir_wcc; +}; + +union SYMLINK3res switch (nfsstat3 status) { +case NFS3_OK: + SYMLINK3resok resok; +default: + SYMLINK3resfail resfail; +}; + +/* + * Arguments to mknod (v3). + */ +struct devicedata3 { + sattr3 dev_attributes; + specdata3 spec; +}; + +union mknoddata3 switch (ftype3 type) { +case NF3CHR: +case NF3BLK: + devicedata3 device; +case NF3SOCK: +case NF3FIFO: + sattr3 pipe_attributes; +default: + void; +}; + +struct MKNOD3args { + diropargs3 where; + mknoddata3 what; +}; + +struct MKNOD3resok { + post_op_fh3 obj; + post_op_attr obj_attributes; + wcc_data dir_wcc; +}; + +struct MKNOD3resfail { + wcc_data dir_wcc; +}; + +union MKNOD3res switch (nfsstat3 status) { +case NFS3_OK: + MKNOD3resok resok; +default: + MKNOD3resfail resfail; +}; + +/* + * Arguments to remove (v3). + */ +struct REMOVE3args { + diropargs3 object; +}; + +struct REMOVE3resok { + wcc_data dir_wcc; +}; + +struct REMOVE3resfail { + wcc_data dir_wcc; +}; + +union REMOVE3res switch (nfsstat3 status) { +case NFS3_OK: + REMOVE3resok resok; +default: + REMOVE3resfail resfail; +}; + +/* + * Arguments to rmdir (v3). + */ +struct RMDIR3args { + diropargs3 object; +}; + +struct RMDIR3resok { + wcc_data dir_wcc; +}; + +struct RMDIR3resfail { + wcc_data dir_wcc; +}; + +union RMDIR3res switch (nfsstat3 status) { +case NFS3_OK: + RMDIR3resok resok; +default: + RMDIR3resfail resfail; +}; + +/* + * Arguments to rename (v3). + */ +struct RENAME3args { + diropargs3 from; + diropargs3 to; +}; + +struct RENAME3resok { + wcc_data fromdir_wcc; + wcc_data todir_wcc; +}; + +struct RENAME3resfail { + wcc_data fromdir_wcc; + wcc_data todir_wcc; +}; + +union RENAME3res switch (nfsstat3 status) { +case NFS3_OK: + RENAME3resok resok; +default: + RENAME3resfail resfail; +}; + +/* + * Arguments to link (v3). + */ +struct LINK3args { + nfs_fh3 file; + diropargs3 link; +}; + +struct LINK3resok { + post_op_attr file_attributes; + wcc_data linkdir_wcc; +}; + +struct LINK3resfail { + post_op_attr file_attributes; + wcc_data linkdir_wcc; +}; + +union LINK3res switch (nfsstat3 status) { +case NFS3_OK: + LINK3resok resok; +default: + LINK3resfail resfail; +}; + +/* + * Arguments to readdir (v3). + */ +struct READDIR3args { + nfs_fh3 dir; + cookie3 cookie; + cookieverf3 cookieverf; + count3 count; +}; + +struct entry3 { + fileid3 fileid; + filename3 name; + cookie3 cookie; + entry3 *nextentry; +}; + +struct dirlist3 { + entry3 *entries; + bool eof; +}; + +struct READDIR3resok { + post_op_attr dir_attributes; + cookieverf3 cookieverf; + dirlist3 reply; +}; + +struct READDIR3resfail { + post_op_attr dir_attributes; +}; + +union READDIR3res switch (nfsstat3 status) { +case NFS3_OK: + READDIR3resok resok; +default: + READDIR3resfail resfail; +}; + +/* + * Arguments to readdirplus (v3). + */ +struct READDIRPLUS3args { + nfs_fh3 dir; + cookie3 cookie; + cookieverf3 cookieverf; + count3 dircount; + count3 maxcount; +}; + +struct entryplus3 { + fileid3 fileid; + filename3 name; + cookie3 cookie; + post_op_attr name_attributes; + post_op_fh3 name_handle; + entryplus3 *nextentry; +}; + +struct dirlistplus3 { + entryplus3 *entries; + bool eof; +}; + +struct READDIRPLUS3resok { + post_op_attr dir_attributes; + cookieverf3 cookieverf; + dirlistplus3 reply; +}; + +struct READDIRPLUS3resfail { + post_op_attr dir_attributes; +}; + +union READDIRPLUS3res switch (nfsstat3 status) { +case NFS3_OK: + READDIRPLUS3resok resok; +default: + READDIRPLUS3resfail resfail; +}; + +/* + * Arguments to fsstat (v3). + */ +struct FSSTAT3args { + nfs_fh3 fsroot; +}; + +struct FSSTAT3resok { + post_op_attr obj_attributes; + size3 tbytes; + size3 fbytes; + size3 abytes; + size3 tfiles; + size3 ffiles; + size3 afiles; + uint32 invarsec; +}; + +struct FSSTAT3resfail { + post_op_attr obj_attributes; +}; + +union FSSTAT3res switch (nfsstat3 status) { +case NFS3_OK: + FSSTAT3resok resok; +default: + FSSTAT3resfail resfail; +}; + +/* + * Arguments to fsinfo (v3). + */ +const FSF3_LINK = 0x0001; +const FSF3_SYMLINK = 0x0002; +const FSF3_HOMOGENEOUS = 0x0008; +const FSF3_CANSETTIME = 0x0010; + +struct FSINFO3args { + nfs_fh3 fsroot; +}; + +struct FSINFO3resok { + post_op_attr obj_attributes; + uint32 rtmax; + uint32 rtpref; + uint32 rtmult; + uint32 wtmax; + uint32 wtpref; + uint32 wtmult; + uint32 dtpref; + size3 maxfilesize; + nfstime3 time_delta; + uint32 properties; +}; + +struct FSINFO3resfail { + post_op_attr obj_attributes; +}; + +union FSINFO3res switch (nfsstat3 status) { +case NFS3_OK: + FSINFO3resok resok; +default: + FSINFO3resfail resfail; +}; + +/* + * Arguments to pathconf (v3). + */ +struct PATHCONF3args { + nfs_fh3 object; +}; + +struct PATHCONF3resok { + post_op_attr obj_attributes; + uint32 linkmax; + uint32 name_max; + bool no_trunc; + bool chown_restricted; + bool case_insensitive; + bool case_preserving; +}; + +struct PATHCONF3resfail { + post_op_attr obj_attributes; +}; + +union PATHCONF3res switch (nfsstat3 status) { +case NFS3_OK: + PATHCONF3resok resok; +default: + PATHCONF3resfail resfail; +}; + +/* + * Arguments to commit (v3). + */ +struct COMMIT3args { + nfs_fh3 file; + offset3 offset; + count3 count; +}; + +struct COMMIT3resok { + wcc_data file_wcc; + writeverf3 verf; +}; + +struct COMMIT3resfail { + wcc_data file_wcc; +}; + +union COMMIT3res switch (nfsstat3 status) { +case NFS3_OK: + COMMIT3resok resok; +default: + COMMIT3resfail resfail; +}; + +#endif /* WANT_NFS3 */ + +/* + * Remote file service routines + */ +program NFS_PROGRAM { + version NFS_VERSION { + void + NFSPROC_NULL(void) = 0; + + attrstat + NFSPROC_GETATTR(nfs_fh) = 1; + + attrstat + NFSPROC_SETATTR(sattrargs) = 2; + + void + NFSPROC_ROOT(void) = 3; + + diropres + NFSPROC_LOOKUP(diropargs) = 4; + + readlinkres + NFSPROC_READLINK(nfs_fh) = 5; + + readres + NFSPROC_READ(readargs) = 6; + + void + NFSPROC_WRITECACHE(void) = 7; + + attrstat + NFSPROC_WRITE(writeargs) = 8; + + diropres + NFSPROC_CREATE(createargs) = 9; + + nfsstat + NFSPROC_REMOVE(diropargs) = 10; + + nfsstat + NFSPROC_RENAME(renameargs) = 11; + + nfsstat + NFSPROC_LINK(linkargs) = 12; + + nfsstat + NFSPROC_SYMLINK(symlinkargs) = 13; + + diropres + NFSPROC_MKDIR(createargs) = 14; + + nfsstat + NFSPROC_RMDIR(diropargs) = 15; + + readdirres + NFSPROC_READDIR(readdirargs) = 16; + + statfsres + NFSPROC_STATFS(nfs_fh) = 17; + } = 2; +} = 100003; +#ifdef WANT_NFS3 +program NFS3_PROGRAM { + version NFS_V3 { + void + NFSPROC3_NULL(void) = 0; + + GETATTR3res + NFSPROC3_GETATTR(GETATTR3args) = 1; + + SETATTR3res + NFSPROC3_SETATTR(SETATTR3args) = 2; + + LOOKUP3res + NFSPROC3_LOOKUP(LOOKUP3args) = 3; + + ACCESS3res + NFSPROC3_ACCESS(ACCESS3args) = 4; + + READLINK3res + NFSPROC3_READLINK(READLINK3args) = 5; + + READ3res + NFSPROC3_READ(READ3args) = 6; + + WRITE3res + NFSPROC3_WRITE(WRITE3args) = 7; + + CREATE3res + NFSPROC3_CREATE(CREATE3args) = 8; + + MKDIR3res + NFSPROC3_MKDIR(MKDIR3args) = 9; + + SYMLINK3res + NFSPROC3_SYMLINK(SYMLINK3args) = 10; + + MKNOD3res + NFSPROC3_MKNOD(MKNOD3args) = 11; + + REMOVE3res + NFSPROC3_REMOVE(REMOVE3args) = 12; + + RMDIR3res + NFSPROC3_RMDIR(RMDIR3args) = 13; + + RENAME3res + NFSPROC3_RENAME(RENAME3args) = 14; + + LINK3res + NFSPROC3_LINK(LINK3args) = 15; + + READDIR3res + NFSPROC3_READDIR(READDIR3args) = 16; + + READDIRPLUS3res + NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17; + + FSSTAT3res + NFSPROC3_FSSTAT(FSSTAT3args) = 18; + + FSINFO3res + NFSPROC3_FSINFO(FSINFO3args) = 19; + + PATHCONF3res + NFSPROC3_PATHCONF(PATHCONF3args) = 20; + + COMMIT3res + NFSPROC3_COMMIT(COMMIT3args) = 21; + } = 3; +} = 100003; +#endif + diff --git a/c/src/exec/librpc/include/rpcsvc/nis.x b/c/src/exec/librpc/include/rpcsvc/nis.x index e69de29bb2..ba6c6d1576 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis.x +++ b/c/src/exec/librpc/include/rpcsvc/nis.x @@ -0,0 +1,466 @@ +%/* +% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for +% * unrestricted use provided that this legend is included on all tape +% * media and as a part of the software program in whole or part. Users +% * may copy or modify Sun RPC without charge, but are not authorized +% * to license or distribute it to anyone else except as part of a product or +% * program developed by the user or with the express written consent of +% * Sun Microsystems, Inc. +% * +% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE +% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR +% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. +% * +% * Sun RPC is provided with no support and without any obligation on the +% * part of Sun Microsystems, Inc. to assist in its use, correction, +% * modification or enhancement. +% * +% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE +% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC +% * OR ANY PART THEREOF. +% * +% * In no event will Sun Microsystems, Inc. be liable for any lost revenue +% * or profits or other special, indirect and consequential damages, even if +% * Sun has been advised of the possibility of such damages. +% * +% * Sun Microsystems, Inc. +% * 2550 Garcia Avenue +% * Mountain View, California 94043 +% */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/nis.x,v 1.3 1999/08/27 23:45:09 peter Exp $"; +%#endif /* not lint */ +#endif + +/* + * From 4.1 : @(#)nis.x 1.61 Copyright 1989 Sun Microsystems + * + * RPC Language Protocol description file for NIS Plus + * This version : 1.61 + * Last Modified : 3/19/91 + */ +#ifdef RPC_HDR +%/* +% * nis.h +% * +% * This file is the main include file for NIS clients. It contains +% * both the client library function defines and the various data +% * structures used by the NIS service. It includes the file nis_tags.h +% * which defines the tag values. This allows the tags to change without +% * having to change the nis.x file. +% * +% * NOTE : DO NOT EDIT THIS FILE! It is automatically generated when +% * rpcgen is run on the nis.x file. Note that there is a +% * simple sed script to remove some unneeded lines. (See the +% * Makefile target nis.h) +% * +% */ +%#include +#endif + +/* This gets stuffed into the source files. */ +#if RPC_HDR +%#include +#endif +/* + * This is just pointless. + */ +#ifdef SUN_STUPIDITY +#if RPC_SVC +%#include "nis_svc.h" +#endif +#endif + +/* Include the RPC Language description of NIS objects */ +#include "nis_object.x" + +/* Errors that can be returned by the service */ +enum nis_error { + NIS_SUCCESS = 0, /* A-ok, let's rock n roll */ + NIS_S_SUCCESS = 1, /* Name found (maybe) */ + NIS_NOTFOUND = 2, /* Name definitely not found */ + NIS_S_NOTFOUND = 3, /* Name maybe not found */ + NIS_CACHEEXPIRED = 4, /* Name exists but cache out of date */ + NIS_NAMEUNREACHABLE = 5, /* Can't get there from here */ + NIS_UNKNOWNOBJ = 6, /* Object type is bogus */ + NIS_TRYAGAIN = 7, /* I'm busy, call back */ + NIS_SYSTEMERROR = 8, /* Out of band failure */ + NIS_CHAINBROKEN = 9, /* First/Next warning */ + NIS_PERMISSION = 10, /* Not enough permission to access */ + NIS_NOTOWNER = 11, /* You don't own it, sorry */ + NIS_NOT_ME = 12, /* I don't serve this name */ + NIS_NOMEMORY = 13, /* Outta VM! Help! */ + NIS_NAMEEXISTS = 14, /* Can't create over another name */ + NIS_NOTMASTER = 15, /* I'm justa secondaray, don't ask me */ + NIS_INVALIDOBJ = 16, /* Object is broken somehow */ + NIS_BADNAME = 17, /* Unparsable name */ + NIS_NOCALLBACK = 18, /* Couldn't talk to call back proc */ + NIS_CBRESULTS = 19, /* Results being called back to you */ + NIS_NOSUCHNAME = 20, /* Name unknown */ + NIS_NOTUNIQUE = 21, /* Value is not uniques (entry) */ + NIS_IBMODERROR = 22, /* Inf. Base. Modify error. */ + NIS_NOSUCHTABLE = 23, /* Name for table was wrong */ + NIS_TYPEMISMATCH = 24, /* Entry and table type mismatch */ + NIS_LINKNAMEERROR = 25, /* Link points to bogus name */ + NIS_PARTIAL = 26, /* Partial success, found table */ + NIS_TOOMANYATTRS = 27, /* Too many attributes */ + NIS_RPCERROR = 28, /* RPC error encountered */ + NIS_BADATTRIBUTE = 29, /* Bad or invalid attribute */ + NIS_NOTSEARCHABLE = 30, /* Non-searchable object searched */ + NIS_CBERROR = 31, /* Error during callback (svc crash) */ + NIS_FOREIGNNS = 32, /* Foreign Namespace */ + NIS_BADOBJECT = 33, /* Malformed object structure */ + NIS_NOTSAMEOBJ = 34, /* Object swapped during deletion */ + NIS_MODFAIL = 35, /* Failure during a Modify. */ + NIS_BADREQUEST = 36, /* Illegal query for table */ + NIS_NOTEMPTY = 37, /* Attempt to remove a non-empty tbl */ + NIS_COLDSTART_ERR = 38, /* Error accesing the cold start file */ + NIS_RESYNC = 39, /* Transaction log too far out of date */ + NIS_FAIL = 40, /* NIS operation failed. */ + NIS_UNAVAIL = 41, /* NIS+ service is unavailable (client) */ + NIS_RES2BIG = 42, /* NIS+ result too big for datagram */ + NIS_SRVAUTH = 43, /* NIS+ server wasn't authenticated. */ + NIS_CLNTAUTH = 44, /* NIS+ Client wasn't authenticated. */ + NIS_NOFILESPACE = 45, /* NIS+ server ran out of disk space */ + NIS_NOPROC = 46, /* NIS+ server couldn't create new proc */ + NIS_DUMPLATER = 47 /* NIS+ server already has dump child */ +}; + + +/* + * Structure definitions for the parameters and results of the actual + * NIS RPC calls. + * + * This is the standard result (in the protocol) of most of the nis + * requests. + */ + +struct nis_result { + nis_error status; /* Status of the response */ + nis_object objects<>; /* objects found */ + netobj cookie; /* Cookie Data */ + u_long zticks; /* server ticks */ + u_long dticks; /* DBM ticks. */ + u_long aticks; /* Cache (accel) ticks */ + u_long cticks; /* Client ticks */ +}; + +/* + * A Name Service request + * This request is used to access the name space, ns_name is the name + * of the object within the namespace and the object is it's value, for + * add/modify, a copy of the original for remove. + */ + +struct ns_request { + nis_name ns_name; /* Name in the NIS name space */ + nis_object ns_object<1>; /* Optional Object (add/remove) */ +}; + +/* + * An information base request + * This request includes the NIS name of the table we wish to search, the + * search criteria in the form of attribute/value pairs and an optional + * callback program number. If the callback program number is provided + * the server will send back objects one at a time, otherwise it will + * return them all in the response. + */ + +struct ib_request { + nis_name ibr_name; /* The name of the Table */ + nis_attr ibr_srch<>; /* The search critereia */ + u_long ibr_flags; /* Optional flags */ + nis_object ibr_obj<1>; /* optional object (add/modify) */ + nis_server ibr_cbhost<1>; /* Optional callback info */ + u_long ibr_bufsize; /* Optional first/next bufsize */ + netobj ibr_cookie; /* The first/next cookie */ +}; + +/* + * This argument to the PING call notifies the replicas that something in + * a directory has changed and this is it's timestamp. The replica will use + * the timestamp to determine if its resync operation was successful. + */ +struct ping_args { + nis_name dir; /* Directory that had the change */ + u_long stamp; /* timestamp of the transaction */ +}; + +/* + * 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 + * 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. + */ +enum log_entry_t { + LOG_NOP = 0, + ADD_NAME = 1, /* Name Added to name space */ + REM_NAME = 2, /* Name removed from name space */ + MOD_NAME_OLD = 3, /* Name was modified in the name space */ + MOD_NAME_NEW = 4, /* Name was modified in the name space */ + ADD_IBASE = 5, /* Entry added to information base */ + REM_IBASE = 6, /* Entry removed from information base */ + MOD_IBASE = 7, /* Entry was modified in information base */ + UPD_STAMP = 8 /* Update timestamp (used as fenceposts) */ +}; + +/* + * This result is returned from the name service when it is requested to + * dump logged entries from its transaction log. Information base updates + * will have the name of the information base in the le_name field and + * a canonical set of attribute/value pairs to fully specify the entry's + * 'name'. + */ +struct log_entry { + u_long le_time; /* Time in seconds */ + log_entry_t le_type; /* Type of log entry */ + nis_name le_princp; /* Principal making the change */ + nis_name le_name; /* Name of table/dir involved */ + nis_attr le_attrs<>; /* List of AV pairs. */ + nis_object le_object; /* Actual object value */ +}; + +struct log_result { + nis_error lr_status; /* The status itself */ + netobj lr_cookie; /* Used by the dump callback */ + log_entry lr_entries<>; /* zero or more entries */ +}; + +struct cp_result { + nis_error cp_status; /* Status of the checkpoint */ + u_long cp_zticks; /* Service 'ticks' */ + u_long cp_dticks; /* Database 'ticks' */ +}; + +/* + * This structure defines a generic NIS tag list. The taglist contains + * zero or tags, each of which is a type and a value. (u_long). + * These are used to report statistics (see tag definitions below) + * and to set or reset state variables. + */ +struct nis_tag { + u_long tag_type; /* Statistic tag (may vary) */ + string tag_val<1024>; /* Statistic value may also vary */ +}; + +struct nis_taglist { + nis_tag tags<>; /* List of tags */ +}; + +struct dump_args { + nis_name da_dir; /* Directory to dump */ + u_long da_time; /* From this timestamp */ + nis_server da_cbhost<1>; /* Callback to use. */ +}; + +struct fd_args { + nis_name dir_name; /* The directory we're looking for */ + nis_name requester; /* Host principal name for signature */ +}; + +struct fd_result { + nis_error status; /* Status returned by function */ + nis_name source; /* Source of this answer */ + opaque dir_data<>; /* Directory Data (XDR'ed) */ + opaque signature<>; /* Signature of the source */ +}; + + +/* + * What's going on here? Well, it's like this. When the service + * is being compiled it wants to have the service definition specific + * info included, and when the client is being compiled it wants that + * info. This includes the appropriate file which was generated by + * make in the protocols directory (probably /usr/include/rpcsvc). + * + * Uhm... guys? With RPC, you aren't supposed to have seperate + * server-specific and client-specific header files. You have one header + * file that's suitable for both. If your code doesn't work using just + * the one header file, I submit to you that it's broken. + * -Bill + */ +#ifdef SUN_STUPIDITY +#ifdef RPC_SVC +%#include "nis_svc.h" +#endif +#ifdef RPC_CLNT +%#include "nis_clnt.h" +#endif +#endif + +program NIS_PROG { + + /* RPC Language description of the NIS+ protocol */ + version NIS_VERSION { + /* The name service functions */ + nis_result NIS_LOOKUP(ns_request) = 1; + nis_result NIS_ADD(ns_request) = 2; + nis_result NIS_MODIFY(ns_request) = 3; + nis_result NIS_REMOVE(ns_request) = 4; + + /* The information base functions */ + nis_result NIS_IBLIST(ib_request) = 5; + nis_result NIS_IBADD(ib_request) = 6; + nis_result NIS_IBMODIFY(ib_request) = 7; + nis_result NIS_IBREMOVE(ib_request) = 8; + nis_result NIS_IBFIRST(ib_request) = 9; + nis_result NIS_IBNEXT(ib_request) = 10; + + /* NIS Administrative functions */ + fd_result NIS_FINDDIRECTORY(fd_args) = 12; + + /* If fetch and optionally reset statistics */ + nis_taglist NIS_STATUS(nis_taglist) = 14; + + /* Dump changes to directory since time in da_time */ + log_result NIS_DUMPLOG(dump_args) = 15; + + /* Dump contents of directory named */ + log_result NIS_DUMP(dump_args) = 16; + + /* Check status of callback thread */ + bool NIS_CALLBACK(netobj) = 17; + + /* Return last update time for named dir */ + u_long NIS_CPTIME(nis_name) = 18; + + /* Checkpoint directory or table named */ + cp_result NIS_CHECKPOINT(nis_name) = 19; + + /* Send 'status changed' ping to replicates */ + void NIS_PING(ping_args) = 20; + + /* Modify server behaviour (such as debugging) */ + nis_taglist NIS_SERVSTATE(nis_taglist) = 21; + + /* Create a Directory */ + nis_error NIS_MKDIR(nis_name) = 22; + + /* Remove a Directory */ + nis_error NIS_RMDIR(nis_name) = 23; + + /* Update public keys of a directory object */ + nis_error NIS_UPDKEYS(nis_name) = 24; + } = 3; +} = 100300; + +/* + * Included below are the defines that become part of nis.h, + * they are technically not part of the protocol, but do define + * key aspects of the implementation and are therefore useful + * in building a conforming server or client. + */ +#if RPC_HDR +%/* +% * Generic "hash" datastructures, used by all types of hashed data. +% */ +%struct nis_hash_data { +% nis_name name; /* NIS name of hashed item */ +% int keychain; /* It's hash key (for pop) */ +% struct nis_hash_data *next; /* Hash collision pointer */ +% struct nis_hash_data *prv_item; /* A serial, doubly linked list */ +% struct nis_hash_data *nxt_item; /* of items in the hash table */ +%}; +%typedef struct nis_hash_data NIS_HASH_ITEM; +% +%struct nis_hash_table { +% NIS_HASH_ITEM *keys[64]; /* A hash table of items */ +% NIS_HASH_ITEM *first; /* The first "item" in serial list */ +%}; +%typedef struct nis_hash_table NIS_HASH_TABLE; +% +%/* Structure for storing dynamically allocated static data */ +%struct nis_sdata { +% void *buf; /* Memory allocation pointer */ +% u_long size; /* Buffer size */ +%}; +% +%/* Generic client creating flags */ +%#define ZMH_VC 1 +%#define ZMH_DG 2 +%#define ZMH_AUTH 4 +% +%/* Testing Access rights for objects */ +% +%#define NIS_READ_ACC 1 +%#define NIS_MODIFY_ACC 2 +%#define NIS_CREATE_ACC 4 +%#define NIS_DESTROY_ACC 8 +%/* Test macros. a == access rights, m == desired rights. */ +%#define WORLD(a, m) (((a) & (m)) != 0) +%#define GROUP(a, m) (((a) & ((m) << 8)) != 0) +%#define OWNER(a, m) (((a) & ((m) << 16)) != 0) +%#define NOBODY(a, m) (((a) & ((m) << 24)) != 0) +% +%#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype) +%#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights) +%#define WORLD_DEFAULT (NIS_READ_ACC) +%#define GROUP_DEFAULT (NIS_READ_ACC << 8) +%#define OWNER_DEFAULT ((NIS_READ_ACC +\ + NIS_MODIFY_ACC +\ + NIS_CREATE_ACC +\ + NIS_DESTROY_ACC) << 16) +%#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT) +% +%/* Result manipulation defines ... */ +%#define NIS_RES_NUMOBJ(x) ((x)->objects.objects_len) +%#define NIS_RES_OBJECT(x) ((x)->objects.objects_val) +%#define NIS_RES_COOKIE(x) ((x)->cookie) +%#define NIS_RES_STATUS(x) ((x)->status) +% +%/* These defines make getting at the variant part of the object easier. */ +%#define TA_data zo_data.objdata_u.ta_data +%#define EN_data zo_data.objdata_u.en_data +%#define DI_data zo_data.objdata_u.di_data +%#define LI_data zo_data.objdata_u.li_data +%#define GR_data zo_data.objdata_u.gr_data +% +%#define __type_of(o) ((o)->zo_data.zo_type) +% +%/* Declarations for the internal subroutines in nislib.c */ +%enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME}; +%typedef enum name_pos name_pos; +% +%/* +% * Defines for getting at column data in entry objects. Because RPCGEN +% * generates some rather wordy structures, we create some defines that +% * collapse the needed keystrokes to access a particular value using +% * these definitions they take an nis_object *, and an int and return +% * a u_char * for Value, and an int for length. +% */ +%#define ENTRY_VAL(obj, col) \ + (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val +%#define ENTRY_LEN(obj, col) \ + (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len +% +%#ifdef __cplusplus +%} +%#endif +% +%/* Prototypes, and extern declarations for the NIS library functions. */ +%#include +%#endif /* __NIS_RPCGEN_H */ +%/* EDIT_START */ +% +%/* +% * nis_3.h +% * +% * This file contains definitions that are only of interest to the actual +% * service daemon and client stubs. Normal users of NIS will not include +% * this file. +% * +% * NOTE : This include file is automatically created by a combination +% * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead +% * and then remake this file. +% */ +%#ifndef __nis_3_h +%#define __nis_3_h +%#ifdef __cplusplus +%extern "C" { +%#endif +#endif diff --git a/c/src/exec/librpc/include/rpcsvc/nis_cache.x b/c/src/exec/librpc/include/rpcsvc/nis_cache.x index e69de29bb2..8343cfd050 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis_cache.x +++ b/c/src/exec/librpc/include/rpcsvc/nis_cache.x @@ -0,0 +1,87 @@ +%/* +% * 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 +% */ + +/* + * nis_cache.x + * + * Copyright (c) 1988-1992 Sun Microsystems Inc + * All Rights Reserved. + */ + +/* From: %#pragma ident "@(#)nis_cache.x 1.11 94/05/03 SMI" */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/nis_cache.x,v 1.3 1999/08/27 23:45:09 peter Exp $"; +%#endif /* not lint */ +#endif + +#ifdef RPC_HDR +%#include +%#include +% +%/* default cache file */ +%#define CACHEFILE "/var/nis/NIS_SHARED_DIRCACHE" +% +%/* clients have to read-lock the cache file, and SVR4 locking requires that */ +%/* the file be writable, but we don't want a world-writable cache file. */ +%/* So... everyone agrees to use a different, world-writable file for the */ +%/* locking operations, but the data is in CACHEFILE. */ +%#define CACHELOCK "/usr/tmp/.NIS_DIR_CACHELOCK" +% +%/* the file containing one trusted XDR'ed directory object. +% * This has to be present for the system to work. +% */ +%#define COLD_START_FILE "/var/nis/NIS_COLD_START" +% +%enum pc_status {HIT, MISS, NEAR_MISS}; +% +%extern int __nis_debuglevel; +% +% +#endif + +#ifdef RPC_CLNT +#ifdef SOLARIS +%#include "../gen/nis_clnt.h" +#else +%#include "nis.h" +#endif +#endif + +program CACHEPROG { + version CACHE_VER_1 { + void NIS_CACHE_ADD_ENTRY(fd_result) = 1; + void NIS_CACHE_REMOVE_ENTRY(directory_obj) = 2; + void NIS_CACHE_READ_COLDSTART(void) = 3; + void NIS_CACHE_REFRESH_ENTRY(string<>) = 4; + } = 1; +} = 100301; diff --git a/c/src/exec/librpc/include/rpcsvc/nis_callback.x b/c/src/exec/librpc/include/rpcsvc/nis_callback.x index e69de29bb2..4e74aa0a2e 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis_callback.x +++ b/c/src/exec/librpc/include/rpcsvc/nis_callback.x @@ -0,0 +1,76 @@ +%/* +% * 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 +% */ + +/* + * nis_callback.x + * + * Copyright (c) 1988-1992 Sun Microsystems Inc + * All Rights Reserved. + */ + +/* From: %#pragma ident "@(#)nis_callback.x 1.7 94/05/03 SMI" */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/nis_callback.x,v 1.3 1999/08/27 23:45:09 peter Exp $"; +%#endif /* not lint */ +#endif + +/* + * "@(#)zns_cback.x 1.2 90/09/10 Copyr 1990 Sun Micro" + * + * RPCL description of the Callback Service. + */ + +#ifdef RPC_HDR +%#include +#endif +#ifdef RPC_XDR +#ifdef SOLARIS +%#include "nis_clnt.h" +#else +%#include "nis.h" +#endif +#endif + +typedef nis_object *obj_p; + +struct cback_data { + obj_p entries<>; /* List of objects */ +}; + +program CB_PROG { + version CB_VERS { + bool CBPROC_RECEIVE(cback_data) = 1; + void CBPROC_FINISH(void) = 2; + void CBPROC_ERROR(nis_error) = 3; + } = 1; +} = 100302; diff --git a/c/src/exec/librpc/include/rpcsvc/nis_db.h b/c/src/exec/librpc/include/rpcsvc/nis_db.h index e69de29bb2..dbdee5aac8 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis_db.h +++ b/c/src/exec/librpc/include/rpcsvc/nis_db.h @@ -0,0 +1,162 @@ +/* + * 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/rpcsvc/nis_db.h,v 1.5 1999/08/27 23:45:09 peter Exp $ + */ + +/* + * Copyright (c) 1991, by Sun Microsystems Inc. + */ + +/* + * This header file defines the interface to the NIS database. All + * implementations of the database must export at least these routines. + * They must also follow the conventions set herein. See the implementors + * guide for specific semantics that are required. + */ + +#ifndef _RPCSVC_NIS_DB_H +#define _RPCSVC_NIS_DB_H + + +/* From: #pragma ident "@(#)nis_db.h 1.8 94/05/03 SMI" */ + +/* + * Note: although the version of shipped with Solaris + * 2.5/2.5.x is actually older than this one (according to the ident + * string), it contains changes and a few added functions. Those changes + * have been hand merged into this file to bring it up to date. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum db_status { + DB_SUCCESS = 0, + DB_NOTFOUND = 1, + DB_NOTUNIQUE = 2, + DB_BADTABLE = 3, + DB_BADQUERY = 4, + DB_BADOBJECT = 5, + DB_MEMORY_LIMIT = 6, + DB_STORAGE_LIMIT = 7, + DB_INTERNAL_ERROR = 8 +}; +typedef enum db_status db_status; + +enum db_action { + DB_LOOKUP = 0, + DB_REMOVE = 1, + DB_ADD = 2, + DB_FIRST = 3, + DB_NEXT = 4, + DB_ALL = 5, + DB_RESET_NEXT = 6 +}; +typedef enum db_action db_action; + +typedef entry_obj *entry_object_p; + +typedef struct { + u_int db_next_desc_len; + char *db_next_desc_val; +} db_next_desc; + +struct db_result { + db_status status; + db_next_desc nextinfo; + struct { + u_int objects_len; + entry_object_p *objects_val; + } objects; + long ticks; +}; +typedef struct db_result db_result; + +/* + * Prototypes for the database functions. + */ + +#if (__STDC__) + +extern bool_t db_initialize(char *); +#ifdef ORIGINAL_DECLS +extern bool_t db_create_table(char *, table_obj *); +extern bool_t db_destroy_table(char *); +#else +extern db_status db_create_table(char *, table_obj *); +extern db_status db_destroy_table(char *); +#endif +extern db_result *db_first_entry(char *, int, nis_attr *); +extern db_result *db_next_entry(char *, db_next_desc *); +extern db_result *db_reset_next_entry(char *, db_next_desc *); +extern db_result *db_list_entries(char *, int, nis_attr *); +extern db_result *db_add_entry(char *, int, nis_attr *, entry_obj *); +extern db_result *db_remove_entry(char *, int, nis_attr *); +extern db_status db_checkpoint(char *); +extern db_status db_standby(char *); +#ifndef ORIGINAL_DECLS +extern db_status db_table_exists(char *); +extern db_status db_unload_table(char *); +extern void db_free_result(db_result *); +#endif + +#else /* Non-prototype definitions */ + +extern bool_t db_initialize(); +#ifdef ORIGINAL_DECLS +extern bool_t db_create_table(); +extern bool_t db_destroy_table(); +#else +extern db_status db_create_table(); +extern db_status db_destroy_table(); +#endif +extern db_result *db_first_entry(); +extern db_result *db_next_entry(); +extern db_result *db_reset_next_entry(); +extern db_result *db_list_entries(); +extern db_result *db_add_entry(); +extern db_result *db_remove_entry(); +extern db_status db_checkpoint(); +extern db_status db_standby(); +#ifndef ORIGINAL_DECLS +extern db_status db_table_exists(); +extern db_status db_unload_table(); +extern void db_free_result(); +#endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RPCSVC_NIS_DB_H */ diff --git a/c/src/exec/librpc/include/rpcsvc/nis_object.x b/c/src/exec/librpc/include/rpcsvc/nis_object.x index e69de29bb2..3156724f1b 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis_object.x +++ b/c/src/exec/librpc/include/rpcsvc/nis_object.x @@ -0,0 +1,317 @@ +%/* +% * 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 +% */ + +/* + * nis_object.x + * + * Copyright (c) 1988-1992 Sun Microsystems Inc + * All Rights Reserved. + */ + +/* From: %#pragma ident "@(#)nis_object.x 1.10 94/05/03 SMI" */ + +#if RPC_HDR +% +%#ifndef __nis_object_h +%#define __nis_object_h +% +#endif +/* + * This file defines the format for a NIS object in RPC language. + * It is included by the main .x file and the database access protocol + * file. It is common because both of them need to deal with the same + * type of object. Generating the actual code though is a bit messy because + * the nis.x file and the nis_dba.x file will generate xdr routines to + * encode/decode objects when only one set is needed. Such is life when + * one is using rpcgen. + * + * Note, the protocol doesn't specify any limits on such things as + * maximum name length, number of attributes, etc. These are enforced + * by the database backend. When you hit them you will no. Also see + * the db_getlimits() function for fetching the limit values. + * + */ + +/* Some manifest constants, chosen to maximize flexibility without + * plugging the wire full of data. + */ +const NIS_MAXSTRINGLEN = 255; +const NIS_MAXNAMELEN = 1024; +const NIS_MAXATTRNAME = 32; +const NIS_MAXATTRVAL = 2048; +const NIS_MAXCOLUMNS = 64; +const NIS_MAXATTR = 16; +const NIS_MAXPATH = 1024; +const NIS_MAXREPLICAS = 128; +const NIS_MAXLINKS = 16; + +const NIS_PK_NONE = 0; /* no public key (unix/sys auth) */ +const NIS_PK_DH = 1; /* Public key is Diffie-Hellman type */ +const NIS_PK_RSA = 2; /* Public key if RSA type */ +const NIS_PK_KERB = 3; /* Use kerberos style authentication */ + +/* + * The fundamental name type of NIS. The name may consist of two parts, + * the first being the fully qualified name, and the second being an + * optional set of attribute/value pairs. + */ +struct nis_attr { + string zattr_ndx<>; /* name of the index */ + opaque zattr_val<>; /* Value for the attribute. */ +}; + +typedef string nis_name<>; /* The NIS name itself. */ + +/* NIS object types are defined by the following enumeration. The numbers + * they use are based on the following scheme : + * 0 - 1023 are reserved for Sun, + * 1024 - 2047 are defined to be private to a particular tree. + * 2048 - 4095 are defined to be user defined. + * 4096 - ... are reserved for future use. + */ + +enum zotypes { + BOGUS_OBJ = 0, /* Uninitialized object structure */ + NO_OBJ = 1, /* NULL object (no data) */ + DIRECTORY_OBJ = 2, /* Directory object describing domain */ + GROUP_OBJ = 3, /* Group object (a list of names) */ + TABLE_OBJ = 4, /* Table object (a database schema) */ + ENTRY_OBJ = 5, /* Entry object (a database record) */ + LINK_OBJ = 6, /* A name link. */ + PRIVATE_OBJ = 7 /* Private object (all opaque data) */ +}; + +/* + * The types of Name services NIS knows about. They are enumerated + * here. The Binder code will use this type to determine if it has + * a set of library routines that will access the indicated name service. + */ +enum nstype { + UNKNOWN = 0, + NIS = 1, /* Nis Plus Service */ + SUNYP = 2, /* Old NIS Service */ + IVY = 3, /* Nis Plus Plus Service */ + DNS = 4, /* Domain Name Service */ + X500 = 5, /* ISO/CCCIT X.500 Service */ + DNANS = 6, /* Digital DECNet Name Service */ + XCHS = 7, /* Xerox ClearingHouse Service */ + CDS= 8 +}; + +/* + * DIRECTORY - The name service object. These objects identify other name + * servers that are serving some portion of the name space. Each has a + * type associated with it. The resolver library will note whether or not + * is has the needed routines to access that type of service. + * The oarmask structure defines an access rights mask on a per object + * type basis for the name spaces. The only bits currently used are + * create and destroy. By enabling or disabling these access rights for + * a specific object type for a one of the accessor entities (owner, + * group, world) the administrator can control what types of objects + * may be freely added to the name space and which require the + * administrator's approval. + */ +struct oar_mask { + u_long oa_rights; /* Access rights mask */ + zotypes oa_otype; /* Object type */ +}; + +struct endpoint { + string uaddr<>; + string family<>; /* Transport family (INET, OSI, etc) */ + string proto<>; /* Protocol (TCP, UDP, CLNP, etc) */ +}; + +/* + * Note: pkey is a netobj which is limited to 1024 bytes which limits the + * keysize to 8192 bits. This is consider to be a reasonable limit for + * the expected lifetime of this service. + */ +struct nis_server { + nis_name name; /* Principal name of the server */ + endpoint ep<>; /* Universal addr(s) for server */ + u_long key_type; /* Public key type */ + netobj pkey; /* server's public key */ +}; + +struct directory_obj { + nis_name do_name; /* Name of the directory being served */ + nstype do_type; /* one of NIS, DNS, IVY, YP, or X.500 */ + nis_server do_servers<>; /* <0> == Primary name server */ + u_long do_ttl; /* Time To Live (for caches) */ + oar_mask do_armask<>; /* Create/Destroy rights by object type */ +}; + +/* + * ENTRY - This is one row of data from an information base. + * The type value is used by the client library to convert the entry to + * it's internal structure representation. The Table name is a back pointer + * to the table where the entry is stored. This allows the client library + * to determine where to send a request if the client wishes to change this + * entry but got to it through a LINK rather than directly. + * If the entry is a "standalone" entry then this field is void. + */ +const EN_BINARY = 1; /* Indicates value is binary data */ +const EN_CRYPT = 2; /* Indicates the value is encrypted */ +const EN_XDR = 4; /* Indicates the value is XDR encoded */ +const EN_MODIFIED = 8; /* Indicates entry is modified. */ +const EN_ASN1 = 64; /* Means contents use ASN.1 encoding */ + +struct entry_col { + u_long ec_flags; /* Flags for this value */ + opaque ec_value<>; /* It's textual value */ +}; + +struct entry_obj { + string en_type<>; /* Type of entry such as "passwd" */ + entry_col en_cols<>; /* Value for the entry */ +}; + +/* + * GROUP - The group object contains a list of NIS principal names. Groups + * are used to authorize principals. Each object has a set of access rights + * for members of its group. Principal names in groups are in the form + * name.directory and recursive groups are expressed as @groupname.directory + */ +struct group_obj { + u_long gr_flags; /* Flags controlling group */ + nis_name gr_members<>; /* List of names in group */ +}; + +/* + * LINK - This is the LINK object. It is quite similar to a symbolic link + * in the UNIX filesystem. The attributes in the main object structure are + * relative to the LINK data and not what it points to (like the file system) + * "modify" privleges here indicate the right to modify what the link points + * at and not to modify that actual object pointed to by the link. + */ +struct link_obj { + zotypes li_rtype; /* Real type of the object */ + nis_attr li_attrs<>; /* Attribute/Values for tables */ + nis_name li_name; /* The object's real NIS name */ +}; + +/* + * TABLE - This is the table object. It implements a simple + * data base that applications and use for configuration or + * administration purposes. The role of the table is to group together + * a set of related entries. Tables are the simple database component + * of NIS. Like many databases, tables are logically divided into columns + * and rows. The columns are labeled with indexes and each ENTRY makes + * up a row. Rows may be addressed within the table by selecting one + * or more indexes, and values for those indexes. Each row which has + * a value for the given index that matches the desired value is returned. + * Within the definition of each column there is a flags variable, this + * variable contains flags which determine whether or not the column is + * searchable, contains binary data, and access rights for the entry objects + * column value. + */ + +const TA_BINARY = 1; /* Means table data is binary */ +const TA_CRYPT = 2; /* Means value should be encrypted */ +const TA_XDR = 4; /* Means value is XDR encoded */ +const TA_SEARCHABLE = 8; /* Means this column is searchable */ +const TA_CASE = 16; /* Means this column is Case Sensitive */ +const TA_MODIFIED = 32; /* Means this columns attrs are modified*/ +const TA_ASN1 = 64; /* Means contents use ASN.1 encoding */ + +struct table_col { + string tc_name<64>; /* Column Name */ + u_long tc_flags; /* control flags */ + u_long tc_rights; /* Access rights mask */ +}; + +struct table_obj { + string ta_type<64>; /* Table type such as "passwd" */ + int ta_maxcol; /* Total number of columns */ + u_char ta_sep; /* Separator character */ + table_col ta_cols<>; /* The number of table indexes */ + string ta_path<>; /* A search path for this table */ +}; + +/* + * This union joins together all of the currently known objects. + */ +union objdata switch (zotypes zo_type) { + case DIRECTORY_OBJ : + struct directory_obj di_data; + case GROUP_OBJ : + struct group_obj gr_data; + case TABLE_OBJ : + struct table_obj ta_data; + case ENTRY_OBJ: + struct entry_obj en_data; + case LINK_OBJ : + struct link_obj li_data; + case PRIVATE_OBJ : + opaque po_data<>; + case NO_OBJ : + void; + case BOGUS_OBJ : + void; + default : + void; +}; + +/* + * This is the basic NIS object data type. It consists of a generic part + * which all objects contain, and a specialized part which varies depending + * on the type of the object. All of the specialized sections have been + * described above. You might have wondered why they all start with an + * integer size, followed by the useful data. The answer is, when the + * server doesn't recognize the type returned it treats it as opaque data. + * And the definition for opaque data is {int size; char *data;}. In this + * way, servers and utility routines that do not understand a given type + * may still pass it around. One has to be careful in setting + * this variable accurately, it must take into account such things as + * XDR padding of structures etc. The best way to set it is to note one's + * position in the XDR encoding stream, encode the structure, look at the + * new position and calculate the size. + */ +struct nis_oid { + u_long ctime; /* Time of objects creation */ + u_long mtime; /* Time of objects modification */ +}; + +struct nis_object { + nis_oid zo_oid; /* object identity verifier. */ + nis_name zo_name; /* The NIS name for this object */ + nis_name zo_owner; /* NIS name of object owner. */ + nis_name zo_group; /* NIS name of access group. */ + nis_name zo_domain; /* The administrator for the object */ + u_long zo_access; /* Access rights (owner, group, world) */ + u_long zo_ttl; /* Object's time to live in seconds. */ + objdata zo_data; /* Data structure for this type */ +}; +#if RPC_HDR +% +%#endif /* if __nis_object_h */ +% +#endif diff --git a/c/src/exec/librpc/include/rpcsvc/nis_tags.h b/c/src/exec/librpc/include/rpcsvc/nis_tags.h index e69de29bb2..0eaee6d442 100644 --- a/c/src/exec/librpc/include/rpcsvc/nis_tags.h +++ b/c/src/exec/librpc/include/rpcsvc/nis_tags.h @@ -0,0 +1,137 @@ +/* + * 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) 1991, Sun Microsystems Inc. + */ + +/* + * nis_tags.h + * + * This file contains the tags and statistics definitions. It is + * automatically included by nis.h + */ + +#ifndef _RPCSVC_NIS_TAGS_H +#define _RPCSVC_NIS_TAGS_H + +/* From: #pragma ident "@(#)nis_tags.h 1.10 94/05/03 SMI" */ +/* from file: zns_tags.h 1.7 Copyright (c) 1990 Sun Microsystems */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ORIGINAL_DECLS +#define NIS_DIR "data" +#endif + +/* Lookup and List function flags */ +#define FOLLOW_LINKS (1<<0) /* Follow link objects */ +#define FOLLOW_PATH (1<<1) /* Follow the path in a table */ +#define HARD_LOOKUP (1<<2) /* Block until successful */ +#define ALL_RESULTS (1<<3) /* Retrieve all results */ +#define NO_CACHE (1<<4) /* Do not return 'cached' results */ +#define MASTER_ONLY (1<<5) /* Get value only from master server */ +#define EXPAND_NAME (1<<6) /* Expand partitially qualified names */ + +/* Semantic modification for table operations flags */ +#define RETURN_RESULT (1<<7) /* Return resulting object to client */ +#define ADD_OVERWRITE (1<<8) /* Allow overwrites on ADD */ +#define REM_MULTIPLE (1<<9) /* Allow wildcard deletes */ +#define MOD_SAMEOBJ (1<<10) /* Check modified object before write */ +#define ADD_RESERVED (1<<11) /* Spare ADD semantic */ +#define REM_RESERVED (1<<12) /* Spare REM semantic */ +#ifdef ORIGINAL_DECLS +#define MOD_RESERVED (1<<13) /* Spare MOD semantic */ +#else +#define MOD_EXCLUSIVE (1<<13) /* Modify no overwrite on modified keys */ +#endif + +/* Transport specific modifications to the operation */ +#define USE_DGRAM (1<<16) /* Use a datagram transport */ +#define NO_AUTHINFO (1<<17) /* Don't bother attaching auth info */ + +/* + * Declarations for "standard" NIS+ tags + * State variable tags have values 0 - 2047 + * Statistic tags have values 2048 - 65535 + * User Tags have values >2^16 + */ +#define TAG_DEBUG 1 /* set debug level */ +#define TAG_STATS 2 /* Enable/disable statistics */ +#define TAG_GCACHE 3 /* Flush the Group Cache */ +#ifndef ORIGINAL_DECLS +#define TAG_GCACHE_ALL TAG_GCACHE +#endif +#define TAG_DCACHE 4 /* Flush the directory cache */ +#ifndef ORIGINAL_DECLS +#define TAG_DCACHE_ONE TAG_DCACHE +#endif +#define TAG_OCACHE 5 /* Flush the Object Cache */ +#define TAG_SECURE 6 /* Set the security level */ +#ifndef ORIGINAL_DECLS +#define TAG_TCACHE_ONE 7 /* Flush the table cache */ +#define TAG_DCACHE_ALL 8 /* Flush entire directory cache */ +#define TAG_TCACHE_ALL 9 /* Flush entire table cache */ +#define TAG_GCACHE_ONE 10 /* Flush one group object */ +#define TAG_DCACHE_ONE_REFRESH 11 /* Flush and refresh one DO */ +#endif + +#define TAG_OPSTATS 2048 /* NIS+ operations statistics */ +#define TAG_THREADS 2049 /* Child process/thread status */ +#define TAG_HEAP 2050 /* Heap usage statistics */ +#define TAG_UPDATES 2051 /* Updates to this service */ +#define TAG_VISIBLE 2052 /* First update that isn't replicated */ +#define TAG_S_DCACHE 2053 /* Directory cache statistics */ +#define TAG_S_OCACHE 2054 /* Object cache statistics */ +#define TAG_S_GCACHE 2055 /* Group cache statistics */ +#define TAG_S_STORAGE 2056 /* Group cache statistics */ +#define TAG_UPTIME 2057 /* Time that server has been up */ +#ifndef ORIGINAL_DECLS +#define TAG_DIRLIST 2058 /* Dir served by this server */ +#define TAG_NISCOMPAT 2059 /* Whether supports NIS compat mode */ +#define TAG_DNSFORWARDING 2060 /* Whether DNS forwarding supported*/ +#define TAG_SECURITY_LEVEL 2061 /* Security level of the server */ +#define TAG_ROOTSERVER 2062 /* Whether root server */ +#endif + +/* + * Declarations for the Group object flags. Currently + * there are only 3. + */ +#define IMPMEM_GROUPS 1 /* Implicit Membership allowed */ +#define RECURS_GROUPS 2 /* Recursive Groups allowed */ +#define NEGMEM_GROUPS 4 /* Negative Groups allowed */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RPCSVC_NIS_TAGS_H */ diff --git a/c/src/exec/librpc/include/rpcsvc/nislib.h b/c/src/exec/librpc/include/rpcsvc/nislib.h index e69de29bb2..9f874d270e 100644 --- a/c/src/exec/librpc/include/rpcsvc/nislib.h +++ b/c/src/exec/librpc/include/rpcsvc/nislib.h @@ -0,0 +1,317 @@ +/* + * 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) 1991, Sun Microsystems Inc. + */ + +/* + * 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. + */ + +#ifndef _RPCSVC_NISLIB_H +#define _RPCSVC_NISLIB_H + +/* From: #pragma ident "@(#)nislib.h 1.16 94/05/03 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct signature { + int signature_len; + char *signature_val; +}; + +#ifdef __STDC__ +extern void nis_freeresult(nis_result *); +extern nis_result * nis_lookup(nis_name, u_long); +extern nis_result * nis_list(nis_name, u_long, + int (*)(nis_name, nis_object *, void *), void *); +extern nis_result * nis_add(nis_name, nis_object *); +extern nis_result * nis_remove(nis_name, nis_object *); +extern nis_result * nis_modify(nis_name, nis_object *); + +extern nis_result * nis_add_entry(nis_name, nis_object *, u_long); +extern nis_result * nis_remove_entry(nis_name, nis_object *, u_long); +extern nis_result * nis_modify_entry(nis_name, nis_object *, u_long); +extern nis_result * nis_first_entry(nis_name); +extern nis_result * nis_next_entry(nis_name, netobj *); + +extern nis_error nis_mkdir(nis_name, nis_server *); +extern nis_error nis_rmdir(nis_name, nis_server *); +extern name_pos nis_dir_cmp(nis_name, nis_name); + +extern nis_name * nis_getnames(nis_name); +extern void nis_freenames(nis_name *); +extern nis_name nis_domain_of(nis_name); +extern nis_name nis_leaf_of(nis_name); +extern nis_name nis_leaf_of_r(const nis_name, char *, size_t); +extern nis_name nis_name_of(nis_name); +extern nis_name nis_local_group(void); +extern nis_name nis_local_directory(void); +extern nis_name nis_local_principal(void); +extern nis_name nis_local_host(void); + +extern void nis_destroy_object(nis_object *); +extern nis_object * nis_clone_object(nis_object *, nis_object *); +extern void nis_print_object(nis_object *); + +extern char * nis_sperrno(nis_error); +extern void nis_perror(nis_error, char *); +extern char * nis_sperror(nis_error, char *); +extern void nis_lerror(nis_error, char *); + +extern void nis_print_group_entry(nis_name); +extern bool_t nis_ismember(nis_name, nis_name); +extern nis_error nis_creategroup(nis_name, u_long); +extern nis_error nis_destroygroup(nis_name); +extern nis_error nis_addmember(nis_name, nis_name); +extern nis_error nis_removemember(nis_name, nis_name); +extern nis_error nis_verifygroup(nis_name); + +extern void nis_freeservlist(nis_server **); +extern nis_server ** nis_getservlist(nis_name); +extern nis_error nis_stats(nis_server *, nis_tag *, int, nis_tag **); +extern nis_error nis_servstate(nis_server *, nis_tag *, int, nis_tag **); +extern void nis_freetags(nis_tag *, int); + +extern nis_result * nis_checkpoint(nis_name); +extern void nis_ping(nis_name, u_long, nis_object *); + +/* + * XXX: PLEASE NOTE THAT THE FOLLOWING FUNCTIONS ARE INTERNAL + * TO NIS+ AND SHOULD NOT BE USED BY ANY APPLICATION PROGRAM. + * THEIR SEMANTICS AND/OR SIGNATURE CAN CHANGE WITHOUT NOTICE. + * SO, PLEASE DO NOT USE THEM. YOU ARE WARNED!!!! + */ + +extern char ** __break_name(nis_name, int *); +extern int __name_distance(char **, char **); +extern nis_result * nis_make_error(nis_error, u_long, u_long, u_long, u_long); +extern nis_attr * __cvt2attr(int *, char **); +extern void nis_free_request(ib_request *); +extern nis_error nis_get_request(nis_name, nis_object *, netobj*, ib_request*); +extern nis_object * nis_read_obj(char *); +extern int nis_write_obj(char *, nis_object *); +extern int nis_in_table(nis_name, NIS_HASH_TABLE *, int *); +extern int nis_insert_item(NIS_HASH_ITEM *, NIS_HASH_TABLE *); +extern NIS_HASH_ITEM * nis_find_item(nis_name, NIS_HASH_TABLE *); +extern NIS_HASH_ITEM * nis_remove_item(nis_name, NIS_HASH_TABLE *); +extern void nis_insert_name(nis_name, NIS_HASH_TABLE *); +extern void nis_remove_name(nis_name, NIS_HASH_TABLE *); +extern CLIENT * nis_make_rpchandle(nis_server *, int, u_long, u_long, u_long, + int, int); +extern void * nis_get_static_storage(struct nis_sdata *, u_long, u_long); +extern char * nis_data(char *); +extern void nis_print_rights(u_long); +extern void nis_print_directory(directory_obj *); +extern void nis_print_group(group_obj *); +extern void nis_print_table(table_obj *); +extern void nis_print_link(link_obj *); +extern void nis_print_entry(entry_obj *); +extern nis_object * nis_get_object(char *, char *, char *, u_long, u_long, + zotypes); +extern nis_server * __nis_init_callback(CLIENT *, + int (*)(nis_name, nis_object *, void *), void *); +extern int nis_getdtblsize(void); +extern int __nis_run_callback(netobj *, u_long, struct timeval *, CLIENT *); + +extern log_result *nis_dumplog(nis_server *, nis_name, u_long); +extern log_result *nis_dump(nis_server *, nis_name, + int (*)(nis_name, nis_object *, void *)); + +extern bool_t __do_ismember(nis_name, nis_name, + nis_result *(*)(nis_name, u_long)); +extern nis_name __nis_map_group(nis_name); +extern nis_name __nis_map_group_r(nis_name, char*, size_t); + +extern nis_error __nis_CacheBind(char *, directory_obj *); +extern nis_error __nis_CacheSearch(char *, directory_obj *); +extern bool_t __nis_CacheRemoveEntry(directory_obj *); +extern void __nis_CacheRestart(void); +extern void __nis_CachePrint(void); +extern void __nis_CacheDumpStatistics(void); +extern bool_t writeColdStartFile(directory_obj *); + +extern CLIENT * __get_ti_clnt(char *, CLIENT *, char **, pid_t *); +extern int __strcmp_case_insens(char *, char *); +extern int __strncmp_case_insens(char *, char *); + +extern fd_result * nis_finddirectory(directory_obj *, nis_name); +extern int __start_clock(int); +extern u_long __stop_clock(int); + +/* + * This particular function is part of the FreeBSD NIS+ implementation + * only. Ideally it should be somewhere else, but it is used by both + * rpc.nisd and nis_cachemgr, and there aren't that many headers common + * to both programs. + */ + +extern struct signature *__nis_calculate_encrypted_cksum(unsigned char *, unsigned int, char *, int); + +#else + +/* Non-prototype definitions (old fashioned C) */ + +extern void nis_freeresult(); +extern nis_result * nis_lookup(); +extern nis_result * nis_list(); +extern nis_result * nis_add(); +extern nis_result * nis_remove(); +extern nis_result * nis_modify(); + +extern nis_result * nis_add_entry(); +extern nis_result * nis_remove_entry(); +extern nis_result * nis_modify_entry(); +extern nis_result * nis_first_entry(); +extern nis_result * nis_next_entry(); + +extern nis_error nis_mkdir(); +extern nis_error nis_rmdir(); +extern name_pos nis_dir_cmp(); + +extern nis_name *nis_getnames(); +extern void nis_freenames(); +extern nis_name nis_domain_of(); +extern nis_name nis_leaf_of(); +extern nis_name nis_leaf_of_r(); +extern nis_name nis_name_of(); +extern nis_name nis_local_group(); +extern nis_name nis_local_directory(); +extern nis_name nis_local_principal(); +extern nis_name nis_local_host(); + +extern void nis_destroy_object(); +extern nis_object * nis_clone_object(); +extern void nis_print_object(); + +extern char * nis_sperrno(); +extern void nis_perror(); +extern char * nis_sperror(); +extern void nis_lerror(); + +extern void nis_print_group_entry(); +extern bool_t nis_ismember(); +extern nis_error nis_creategroup(); +extern nis_error nis_destroygroup(); +extern nis_error nis_addmember(); +extern nis_error nis_removemember(); +extern nis_error nis_verifygroup(); + +extern void nis_freeservlist(); +extern nis_server ** nis_getservlist(); +extern nis_error nis_stats(); +extern nis_error nis_servstate(); +extern void nis_freetags(); + +extern nis_result * nis_checkpoint(); +extern void nis_ping(); + +/* + * XXX: PLEASE NOTE THAT THE FOLLOWING FUNCTIONS ARE INTERNAL + * TO NIS+ AND SHOULD NOT BE USED BY ANY APPLICATION PROGRAM. + * THEIR SEMANTICS AND/OR SIGNATURE CAN CHANGE WITHOUT NOTICE. + * SO, PLEASE DO NOT USE THEM. YOU ARE WARNED!!!! + */ +extern char ** __break_name(); +extern int __name_distance(); +extern nis_result * nis_make_error(); +extern nis_attr * __cvt2attr(); +extern void nis_free_request(); +extern nis_error nis_get_request(); +extern nis_object * nis_read_obj(); +extern int nis_write_obj(); +extern int nis_in_table(); +extern int nis_insert_item(); +extern NIS_HASH_ITEM * nis_find_item(); +extern NIS_HASH_ITEM * nis_remove_item(); +extern void nis_insert_name(); +extern void nis_remove_name(); +extern CLIENT * nis_make_rpchandle(); +extern void * nis_get_static_storage(); +extern char * nis_data(); + +extern void nis_print_rights(); +extern void nis_print_directory(); +extern void nis_print_group(); +extern void nis_print_table(); +extern void nis_print_link(); +extern void nis_print_entry(); +extern nis_object * nis_get_object(); + +extern nis_server * __nis_init_callback(); +extern int nis_getdtblsize(); +extern int __nis_run_callback(); + +extern log_result * nis_dump(); +extern log_result * nis_dumplog(); + +extern bool_t __do_ismember(); +extern nis_name __nis_map_group(); +extern nis_name __nis_map_group_r(); + + +extern nis_error __nis_CacheBind(); +extern directory_obj * __nis_CacheSearch(); +extern bool_t __nis_CacheRemoveEntry(); +extern void __nis_CacheRestart(); +extern void __nis_CachePrint(); +extern void __nis_CacheDumpStatistics(); +extern bool_t writeColdStartFile(); + +extern CLIENT * __get_ti_clnt(); +extern int __strcmp_case_insens(); +extern int __strncmp_case_insens(); + +extern fd_result * nis_finddirectory(); +extern int __start_clock(); +extern u_long __stop_clock(); + +/* + * This particular function is part of the FreeBSD NIS+ implementation + * only. Ideally it should be somewhere else, but it is used by both + * rpc.nisd and nis_cachemgr, and there aren't that many headers common + * to both programs. + */ + +extern struct signature *__nis_calculate_encrypted_cksum(); + +#endif + +#define NUL '\0' + +#ifdef __cplusplus +} +#endif + +#endif /* _RPCSVC_NISLIB_H */ diff --git a/c/src/exec/librpc/include/rpcsvc/nlm_prot.x b/c/src/exec/librpc/include/rpcsvc/nlm_prot.x index e69de29bb2..675bb6d1bc 100644 --- a/c/src/exec/librpc/include/rpcsvc/nlm_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/nlm_prot.x @@ -0,0 +1,184 @@ +/* @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC */ +/* @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro */ + +/* + * Network lock manager protocol definition + * Copyright (C) 1986 Sun Microsystems, Inc. + * + * protocol used between local lock manager and remote lock manager + */ + +#ifdef RPC_HDR +%#define LM_MAXSTRLEN 1024 +%#define MAXNAMELEN LM_MAXSTRLEN+1 +#else +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/nlm_prot.x,v 1.8 1999/08/27 23:45:10 peter Exp $"; +%#endif /* not lint */ +#endif + +/* + * status of a call to the lock manager + */ +enum nlm_stats { + nlm_granted = 0, + nlm_denied = 1, + nlm_denied_nolocks = 2, + nlm_blocked = 3, + nlm_denied_grace_period = 4 +}; + +struct nlm_holder { + bool exclusive; + int svid; + netobj oh; + unsigned l_offset; + unsigned l_len; +}; + +union nlm_testrply switch (nlm_stats stat) { + case nlm_denied: + struct nlm_holder holder; + default: + void; +}; + +struct nlm_stat { + nlm_stats stat; +}; + +struct nlm_res { + netobj cookie; + nlm_stat stat; +}; + +struct nlm_testres { + netobj cookie; + nlm_testrply stat; +}; + +struct nlm_lock { + string caller_name; + netobj fh; /* identify a file */ + netobj oh; /* identify owner of a lock */ + int svid; /* generated from pid for svid */ + unsigned l_offset; + unsigned l_len; +}; + +struct nlm_lockargs { + netobj cookie; + bool block; + bool exclusive; + struct nlm_lock alock; + bool reclaim; /* used for recovering locks */ + int state; /* specify local status monitor state */ +}; + +struct nlm_cancargs { + netobj cookie; + bool block; + bool exclusive; + struct nlm_lock alock; +}; + +struct nlm_testargs { + netobj cookie; + bool exclusive; + struct nlm_lock alock; +}; + +struct nlm_unlockargs { + netobj cookie; + struct nlm_lock alock; +}; + + +#ifdef RPC_HDR +%/* +% * The following enums are actually bit encoded for efficient +% * boolean algebra.... DON'T change them..... +% */ +#endif +enum fsh_mode { + fsm_DN = 0, /* deny none */ + fsm_DR = 1, /* deny read */ + fsm_DW = 2, /* deny write */ + fsm_DRW = 3 /* deny read/write */ +}; + +enum fsh_access { + fsa_NONE = 0, /* for completeness */ + fsa_R = 1, /* read only */ + fsa_W = 2, /* write only */ + fsa_RW = 3 /* read/write */ +}; + +struct nlm_share { + string caller_name; + netobj fh; + netobj oh; + fsh_mode mode; + fsh_access access; +}; + +struct nlm_shareargs { + netobj cookie; + nlm_share share; + bool reclaim; +}; + +struct nlm_shareres { + netobj cookie; + nlm_stats stat; + int sequence; +}; + +struct nlm_notify { + string name; + long state; +}; + +/* + * Over-the-wire protocol used between the network lock managers + */ + +program NLM_PROG { + version NLM_VERS { + + nlm_testres NLM_TEST(struct nlm_testargs) = 1; + + nlm_res NLM_LOCK(struct nlm_lockargs) = 2; + + nlm_res NLM_CANCEL(struct nlm_cancargs) = 3; + nlm_res NLM_UNLOCK(struct nlm_unlockargs) = 4; + + /* + * remote lock manager call-back to grant lock + */ + nlm_res NLM_GRANTED(struct nlm_testargs)= 5; + /* + * message passing style of requesting lock + */ + void NLM_TEST_MSG(struct nlm_testargs) = 6; + void NLM_LOCK_MSG(struct nlm_lockargs) = 7; + void NLM_CANCEL_MSG(struct nlm_cancargs) =8; + void NLM_UNLOCK_MSG(struct nlm_unlockargs) = 9; + void NLM_GRANTED_MSG(struct nlm_testargs) = 10; + void NLM_TEST_RES(nlm_testres) = 11; + void NLM_LOCK_RES(nlm_res) = 12; + void NLM_CANCEL_RES(nlm_res) = 13; + void NLM_UNLOCK_RES(nlm_res) = 14; + void NLM_GRANTED_RES(nlm_res) = 15; + } = 1; + + version NLM_VERSX { + nlm_shareres NLM_SHARE(nlm_shareargs) = 20; + nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21; + nlm_res NLM_NM_LOCK(nlm_lockargs) = 22; + void NLM_FREE_ALL(nlm_notify) = 23; + } = 3; + +} = 100021; + diff --git a/c/src/exec/librpc/include/rpcsvc/pmap_prot.x b/c/src/exec/librpc/include/rpcsvc/pmap_prot.x index e69de29bb2..d90e2c503b 100644 --- a/c/src/exec/librpc/include/rpcsvc/pmap_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/pmap_prot.x @@ -0,0 +1,285 @@ +%/* +% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for +% * unrestricted use provided that this legend is included on all tape +% * media and as a part of the software program in whole or part. Users +% * may copy or modify Sun RPC without charge, but are not authorized +% * to license or distribute it to anyone else except as part of a product or +% * program developed by the user. +% * +% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE +% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR +% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. +% * +% * Sun RPC is provided with no support and without any obligation on the +% * part of Sun Microsystems, Inc. to assist in its use, correction, +% * modification or enhancement. +% * +% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE +% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC +% * OR ANY PART THEREOF. +% * +% * In no event will Sun Microsystems, Inc. be liable for any lost revenue +% * or profits or other special, indirect and consequential damages, even if +% * Sun has been advised of the possibility of such damages. +% * +% * Sun Microsystems, Inc. +% * 2550 Garcia Avenue +% * Mountain View, California 94043 +% */ +%/* +% * Copyright (c) 1984,1989 by Sun Microsystems, Inc. +% */ + +%/* from pmap_prot.x */ + +#ifdef RPC_HDR +% +%#pragma ident "@(#)pmap_prot.x 1.6 94/04/29 SMI" +% +%#ifndef _KERNEL +% +#endif + +/* + * Port Mapper Protocol Specification (in RPC Language) + * derived from RFC 1057 + */ + +%/* +% * Protocol for the local binder service, or pmap. +% * +% * Copyright (C) 1984, Sun Microsystems, Inc. +% * +% * The following procedures are supported by the protocol: +% * +% * PMAPPROC_NULL() returns () +% * takes nothing, returns nothing +% * +% * PMAPPROC_SET(struct pmap) returns (bool_t) +% * TRUE is success, FALSE is failure. Registers the tuple +% * [prog, vers, prot, port]. +% * +% * PMAPPROC_UNSET(struct pmap) returns (bool_t) +% * TRUE is success, FALSE is failure. Un-registers pair +% * [prog, vers]. prot and port are ignored. +% * +% * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). +% * 0 is failure. Otherwise returns the port number where the pair +% * [prog, vers] is registered. It may lie! +% * +% * PMAPPROC_DUMP() RETURNS (struct pmaplist_ptr) +% * +% * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) +% * RETURNS (port, string<>); +% * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, +% * encapsulatedargs); +% * Calls the procedure on the local machine. If it is not registered, +% * this procedure is quite; ie it does not return error information!!! +% * This procedure only is supported on rpc/udp and calls via +% * rpc/udp. This routine only passes null authentication parameters. +% * This file has no interface to xdr routines for PMAPPROC_CALLIT. +% * +% * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. +% */ +% +const PMAPPORT = 111; /* portmapper port number */ +% +% +%/* +% * A mapping of (program, version, protocol) to port number +% */ + +struct pmap { + unsigned long pm_prog; + unsigned long pm_vers; + unsigned long pm_prot; + unsigned long pm_port; +}; +#ifdef RPC_HDR +% +%typedef pmap PMAP; +% +#endif +% +%/* +% * Supported values for the "prot" field +% */ +% +const PMAP_IPPROTO_TCP = 6; /* protocol number for TCP/IP */ +const PMAP_IPPROTO_UDP = 17; /* protocol number for UDP/IP */ +% +% +%/* +% * A list of mappings +% * +% * Below are two definitions for the pmaplist structure. This is done because +% * xdr_pmaplist() is specified to take a struct pmaplist **, rather than a +% * struct pmaplist * that rpcgen would produce. One version of the pmaplist +% * structure (actually called pm__list) is used with rpcgen, and the other is +% * defined only in the header file for compatibility with the specified +% * interface. +% */ + +struct pm__list { + pmap pml_map; + struct pm__list *pml_next; +}; + +typedef pm__list *pmaplist_ptr; /* results of PMAPPROC_DUMP */ + +#ifdef RPC_HDR +% +%typedef struct pm__list pmaplist; +%typedef struct pm__list PMAPLIST; +% +%#ifndef __cplusplus +%struct pmaplist { +% PMAP pml_map; +% struct pmaplist *pml_next; +%}; +%#endif +% +%#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 +% +#endif + +% +%/* +% * Arguments to callit +% */ + +struct rmtcallargs { + unsigned long prog; + unsigned long vers; + unsigned long proc; + opaque args<>; +}; +#ifdef RPC_HDR +% +%/* +% * Client-side only representation of rmtcallargs structure. +% * +% * The routine that XDRs the rmtcallargs structure must deal with the +% * opaque arguments in the "args" structure. xdr_rmtcall_args() 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 knows the args structure already. So we use a +% * different "XDR" structure on the client side, p_rmtcallargs, which includes +% * the args' XDR routine. +% */ +%struct p_rmtcallargs { +% u_long prog; +% u_long vers; +% u_long proc; +% struct { +% u_int args_len; +% char *args_val; +% } args; +% xdrproc_t xdr_args; /* encodes args */ +%}; +% +#endif /* def RPC_HDR */ +% +% +%/* +% * Results of callit +% */ + +struct rmtcallres { + unsigned long port; + opaque res<>; +}; +#ifdef RPC_HDR +% +%/* +% * Client-side only representation of rmtcallres structure. +% */ +%struct p_rmtcallres { +% u_long port; +% struct { +% u_int res_len; +% char *res_val; +% } res; +% xdrproc_t xdr_res; /* decodes res */ +%}; +% +#endif /* def RPC_HDR */ + +/* + * Port mapper procedures + */ + +program PMAPPROG { + version PMAPVERS { + void + PMAPPROC_NULL(void) = 0; + + bool + PMAPPROC_SET(pmap) = 1; + + bool + PMAPPROC_UNSET(pmap) = 2; + + unsigned long + PMAPPROC_GETPORT(pmap) = 3; + + pmaplist_ptr + PMAPPROC_DUMP(void) = 4; + + rmtcallres + PMAPPROC_CALLIT(rmtcallargs) = 5; + } = 2; +} = 100000; +% +#ifdef RPC_HDR +%#define PMAPVERS_PROTO ((u_long)2) +%#define PMAPVERS_ORIG ((u_long)1) +% +%#else /* ndef _KERNEL */ +% +%#include +% +%#ifdef __cplusplus +%extern "C" { +%#endif +% +%#define PMAPPORT 111 +% +%struct pmap { +% long unsigned pm_prog; +% long unsigned pm_vers; +% long unsigned pm_prot; +% 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; +% struct pmaplist *pml_next; +%}; +%typedef struct pmaplist PMAPLIST; +%typedef struct pmaplist *pmaplist_ptr; +% +% +%#ifdef __cplusplus +%} +%#endif +% +%#endif /* ndef _KERNEL */ +#endif + diff --git a/c/src/exec/librpc/include/rpcsvc/rex.x b/c/src/exec/librpc/include/rpcsvc/rex.x index e69de29bb2..928efa21e7 100644 --- a/c/src/exec/librpc/include/rpcsvc/rex.x +++ b/c/src/exec/librpc/include/rpcsvc/rex.x @@ -0,0 +1,235 @@ +/* + * 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 + */ + +/* + * Remote execution (rex) protocol specification + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)rex.x 1.3 87/09/18 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)rex.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/rex.x,v 1.6 1999/08/27 23:45:10 peter Exp $"; +%#endif /* not lint */ +#endif + +const STRINGSIZE = 1024; +typedef string rexstring<1024>; + +/* + * values to pass to REXPROC_SIGNAL + */ +const SIGINT = 2; /* interrupt */ + +/* + * Values for rst_flags, below + */ +const REX_INTERACTIVE = 1; /* interactive mode */ + +struct rex_start { + rexstring rst_cmd<>; /* list of command and args */ + rexstring rst_host; /* working directory host name */ + rexstring rst_fsname; /* working directory file system name */ + rexstring rst_dirwithin;/* working directory within file system */ + rexstring rst_env<>; /* list of environment */ + unsigned int rst_port0; /* port for stdin */ + unsigned int rst_port1; /* port for stdout */ + unsigned int rst_port2; /* port for stderr */ + unsigned int rst_flags; /* options - see const above */ +}; + +struct rex_result { + int rlt_stat; /* integer status code */ + rexstring rlt_message; /* string message for human consumption */ +}; + + +struct sgttyb { + unsigned four; /* always equals 4 */ + opaque chars[4]; + /* chars[0] == input speed */ + /* chars[1] == output speed */ + /* chars[2] == kill character */ + /* chars[3] == erase character */ + unsigned flags; +}; +/* values for speeds above (baud rates) */ +const B0 = 0; +const B50 = 1; +const B75 = 2; +const B110 = 3; +const B134 = 4; +const B150 = 5; +const B200 = 6; +const B300 = 7; +const B600 = 8; +const B1200 = 9; +const B1800 = 10; +const B2400 = 11; +const B4800 = 12; +const B9600 = 13; +const B19200 = 14; +const B38400 = 15; + +/* values for flags above */ +const TANDEM = 0x00000001; /* send stopc on out q full */ +const CBREAK = 0x00000002; /* half-cooked mode */ +const LCASE = 0x00000004; /* simulate lower case */ +const ECHO = 0x00000008; /* echo input */ +const CRMOD = 0x00000010; /* map \r to \r\n on output */ +const RAW = 0x00000020; /* no i/o processing */ +const ODDP = 0x00000040; /* get/send odd parity */ +const EVENP = 0x00000080; /* get/send even parity */ +const ANYP = 0x000000c0; /* get any parity/send none */ +const NLDELAY = 0x00000300; /* \n delay */ +const NL0 = 0x00000000; +const NL1 = 0x00000100; /* tty 37 */ +const NL2 = 0x00000200; /* vt05 */ +const NL3 = 0x00000300; +const TBDELAY = 0x00000c00; /* horizontal tab delay */ +const TAB0 = 0x00000000; +const TAB1 = 0x00000400; /* tty 37 */ +const TAB2 = 0x00000800; +const XTABS = 0x00000c00; /* expand tabs on output */ +const CRDELAY = 0x00003000; /* \r delay */ +const CR0 = 0x00000000; +const CR1 = 0x00001000; /* tn 300 */ +const CR2 = 0x00002000; /* tty 37 */ +const CR3 = 0x00003000; /* concept 100 */ +const VTDELAY = 0x00004000; /* vertical tab delay */ +const FF0 = 0x00000000; +const FF1 = 0x00004000; /* tty 37 */ +const BSDELAY = 0x00008000; /* \b delay */ +const BS0 = 0x00000000; +const BS1 = 0x00008000; +const CRTBS = 0x00010000; /* do backspacing for crt */ +const PRTERA = 0x00020000; /* \ ... / erase */ +const CRTERA = 0x00040000; /* " \b " to wipe out char */ +const TILDE = 0x00080000; /* hazeltine tilde kludge */ +const MDMBUF = 0x00100000; /* start/stop output on carrier intr */ +const LITOUT = 0x00200000; /* literal output */ +const TOSTOP = 0x00400000; /* SIGTTOU on background output */ +const FLUSHO = 0x00800000; /* flush output to terminal */ +const NOHANG = 0x01000000; /* no SIGHUP on carrier drop */ +const L001000 = 0x02000000; +const CRTKIL = 0x04000000; /* kill line with " \b " */ +const PASS8 = 0x08000000; +const CTLECH = 0x10000000; /* echo control chars as ^X */ +const PENDIN = 0x20000000; /* tp->t_rawq needs reread */ +const DECCTQ = 0x40000000; /* only ^Q starts after ^S */ +const NOFLSH = 0x80000000; /* no output flush on signal */ + +struct tchars { + unsigned six; /* always equals 6 */ + opaque chars[6]; + /* chars[0] == interrupt char */ + /* chars[1] == quit char */ + /* chars[2] == start output char */ + /* chars[3] == stop output char */ + /* chars[4] == end-of-file char */ + /* chars[5] == input delimeter (like nl) */ +}; + +struct ltchars { + unsigned six; /* always equals 6 */ + opaque chars[6]; + /* chars[0] == stop process signal */ + /* chars[1] == delayed stop process signal */ + /* chars[2] == reprint line */ + /* chars[3] == flush output */ + /* chars[4] == word erase */ + /* chars[5] == literal next character */ + unsigned mode; +}; + +struct rex_ttysize { + int ts_lines; + int ts_cols; +}; + +struct rex_ttymode { + sgttyb basic; /* standard unix tty flags */ + tchars more; /* interrupt, kill characters, etc. */ + ltchars yetmore; /* special Berkeley characters */ + unsigned andmore; /* and Berkeley modes */ +}; + +/* values for andmore above */ +const LCRTBS = 0x0001; /* do backspacing for crt */ +const LPRTERA = 0x0002; /* \ ... / erase */ +const LCRTERA = 0x0004; /* " \b " to wipe out char */ +const LTILDE = 0x0008; /* hazeltine tilde kludge */ +const LMDMBUF = 0x0010; /* start/stop output on carrier intr */ +const LLITOUT = 0x0020; /* literal output */ +const LTOSTOP = 0x0040; /* SIGTTOU on background output */ +const LFLUSHO = 0x0080; /* flush output to terminal */ +const LNOHANG = 0x0100; /* no SIGHUP on carrier drop */ +const LL001000 = 0x0200; +const LCRTKIL = 0x0400; /* kill line with " \b " */ +const LPASS8 = 0x0800; +const LCTLECH = 0x1000; /* echo control chars as ^X */ +const LPENDIN = 0x2000; /* needs reread */ +const LDECCTQ = 0x4000; /* only ^Q starts after ^S */ +const LNOFLSH = 0x8000; /* no output flush on signal */ + +program REXPROG { + version REXVERS { + + /* + * Start remote execution + */ + rex_result + REXPROC_START(rex_start) = 1; + + /* + * Wait for remote execution to terminate + */ + rex_result + REXPROC_WAIT(void) = 2; + + /* + * Send tty modes + */ + void + REXPROC_MODES(rex_ttymode) = 3; + + /* + * Send window size change + */ + void + REXPROC_WINCH(rex_ttysize) = 4; + + /* + * Send other signal + */ + void + REXPROC_SIGNAL(int) = 5; + } = 1; +} = 100017; diff --git a/c/src/exec/librpc/include/rpcsvc/rnusers.x b/c/src/exec/librpc/include/rpcsvc/rnusers.x index e69de29bb2..f862c6192b 100644 --- a/c/src/exec/librpc/include/rpcsvc/rnusers.x +++ b/c/src/exec/librpc/include/rpcsvc/rnusers.x @@ -0,0 +1,123 @@ +/* + * 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 + */ + +/* + * Find out about remote users + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)rnusers.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)rnusers.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/rnusers.x,v 1.6 1999/08/27 23:45:10 peter Exp $"; +%#endif /* not lint */ +#endif + +const MAXUSERS = 100; +const MAXUTLEN = 256; + +struct utmp { + string ut_line; + string ut_name; + string ut_host; + int ut_time; +}; + + +struct utmpidle { + utmp ui_utmp; + unsigned int ui_idle; +}; + +typedef utmp utmparr; + +typedef utmpidle utmpidlearr; + +const RUSERS_MAXUSERLEN = 32; +const RUSERS_MAXLINELEN = 32; +const RUSERS_MAXHOSTLEN = 257; + +struct rusers_utmp { + string ut_user; /* aka ut_name */ + string ut_line; /* device */ + string ut_host; /* host user logged on from */ + int ut_type; /* type of entry */ + int ut_time; /* time entry was made */ + unsigned int ut_idle; /* minutes idle */ +}; + +typedef rusers_utmp utmp_array<>; + +program RUSERSPROG { + /* + * Old version does not include idle information + */ + version RUSERSVERS_ORIG { + int + RUSERSPROC_NUM(void) = 1; + + utmparr + RUSERSPROC_NAMES(void) = 2; + + utmparr + RUSERSPROC_ALLNAMES(void) = 3; + } = 1; + + /* + * Includes idle information + */ + version RUSERSVERS_IDLE { + int + RUSERSPROC_NUM(void) = 1; + + utmpidlearr + RUSERSPROC_NAMES(void) = 2; + + utmpidlearr + RUSERSPROC_ALLNAMES(void) = 3; + } = 2; + + /* + * Version 3 rusers procedures (from Solaris). + * (Thanks a lot Sun.) + */ + version RUSERSVERS_3 { + int + RUSERSPROC_NUM(void) = 1; + + utmp_array + RUSERSPROC_NAMES(void) = 2; + + utmp_array + RUSERSPROC_ALLNAMES(void) = 3; + } = 3; + +} = 100002; + diff --git a/c/src/exec/librpc/include/rpcsvc/rquota.x b/c/src/exec/librpc/include/rpcsvc/rquota.x index e69de29bb2..72864d1c69 100644 --- a/c/src/exec/librpc/include/rpcsvc/rquota.x +++ b/c/src/exec/librpc/include/rpcsvc/rquota.x @@ -0,0 +1,67 @@ +/* + * Remote quota protocol + * Requires unix authentication + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/rquota.x,v 1.6 1999/08/27 23:45:10 peter Exp $"; +%#endif /* not lint */ +#endif + +const RQ_PATHLEN = 1024; + +struct getquota_args { + string gqa_pathp; /* path to filesystem of interest */ + int gqa_uid; /* inquire about quota for uid */ +}; + +/* + * remote quota structure + */ +struct rquota { + int rq_bsize; /* block size for block counts */ + bool rq_active; /* indicates whether quota is active */ + unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */ + unsigned int rq_bsoftlimit; /* preferred limit on disk blks */ + unsigned int rq_curblocks; /* current block count */ + unsigned int rq_fhardlimit; /* absolute limit on allocated files */ + unsigned int rq_fsoftlimit; /* preferred file limit */ + unsigned int rq_curfiles; /* current # allocated files */ + unsigned int rq_btimeleft; /* time left for excessive disk use */ + unsigned int rq_ftimeleft; /* time left for excessive files */ +}; + +enum gqr_status { + Q_OK = 1, /* quota returned */ + Q_NOQUOTA = 2, /* noquota for uid */ + Q_EPERM = 3 /* no permission to access quota */ +}; + +union getquota_rslt switch (gqr_status status) { +case Q_OK: + rquota gqr_rquota; /* valid if status == Q_OK */ +case Q_NOQUOTA: + void; +case Q_EPERM: + void; +}; + +program RQUOTAPROG { + version RQUOTAVERS { + /* + * Get all quotas + */ + getquota_rslt + RQUOTAPROC_GETQUOTA(getquota_args) = 1; + + /* + * Get active quotas only + */ + getquota_rslt + RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2; + } = 1; +} = 100011; diff --git a/c/src/exec/librpc/include/rpcsvc/rstat.x b/c/src/exec/librpc/include/rpcsvc/rstat.x index e69de29bb2..fee9d52032 100644 --- a/c/src/exec/librpc/include/rpcsvc/rstat.x +++ b/c/src/exec/librpc/include/rpcsvc/rstat.x @@ -0,0 +1,151 @@ +/* + * 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 + */ + +/* + * Gather statistics on remote machines + */ + +#ifdef RPC_HDR + +%#ifndef FSCALE +%/* +% * Scale factor for scaled integers used to count load averages. +% */ +%#define FSHIFT 8 /* bits to right of fixed binary point */ +%#define FSCALE (1<; +}; + +struct my_id { + string my_name; /* name of the site iniates the monitoring request*/ + int my_prog; /* rpc program # of the requesting process */ + int my_vers; /* rpc version # of the requesting process */ + int my_proc; /* rpc procedure # of the requesting process */ +}; + +struct mon_id { + string mon_name; /* name of the site to be monitored */ + struct my_id my_id; +}; + + +struct mon{ + struct mon_id mon_id; + opaque priv[16]; /* private information to store at monitor for requesting process */ +}; + + +/* + * state # of status monitor monitonically increases each time + * status of the site changes: + * an even number (>= 0) indicates the site is down and + * an odd number (> 0) indicates the site is up; + */ +struct sm_stat { + int state; /* state # of status monitor */ +}; + +enum res { + stat_succ = 0, /* status monitor agrees to monitor */ + stat_fail = 1 /* status monitor cannot monitor */ +}; + +struct sm_stat_res { + res res_stat; + int state; +}; + +/* + * structure of the status message sent back by the status monitor + * when monitor site status changes + */ +struct status { + string mon_name; + int state; + opaque priv[16]; /* stored private information */ +}; diff --git a/c/src/exec/librpc/include/rpcsvc/spray.x b/c/src/exec/librpc/include/rpcsvc/spray.x index e69de29bb2..a4d086af48 100644 --- a/c/src/exec/librpc/include/rpcsvc/spray.x +++ b/c/src/exec/librpc/include/rpcsvc/spray.x @@ -0,0 +1,90 @@ +/* + * 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 + */ + +/* + * Spray a server with packets + * Useful for testing flakiness of network interfaces + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)spray.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)spray.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/spray.x,v 1.6 1999/08/27 23:45:11 peter Exp $"; +%#endif /* not lint */ +#endif + +const SPRAYMAX = 8845; /* max amount can spray */ + +/* + * GMT since 0:00, 1 January 1970 + */ +struct spraytimeval { + unsigned int sec; + unsigned int usec; +}; + +/* + * spray statistics + */ +struct spraycumul { + unsigned int counter; + spraytimeval clock; +}; + +/* + * spray data + */ +typedef opaque sprayarr; + +program SPRAYPROG { + version SPRAYVERS { + /* + * Just throw away the data and increment the counter + * This call never returns, so the client should always + * time it out. + */ + void + SPRAYPROC_SPRAY(sprayarr) = 1; + + /* + * Get the value of the counter and elapsed time since + * last CLEAR. + */ + spraycumul + SPRAYPROC_GET(void) = 2; + + /* + * Clear the counter and reset the elapsed time + */ + void + SPRAYPROC_CLEAR(void) = 3; + } = 1; +} = 100012; diff --git a/c/src/exec/librpc/include/rpcsvc/yp.x b/c/src/exec/librpc/include/rpcsvc/yp.x index e69de29bb2..aa872653ff 100644 --- a/c/src/exec/librpc/include/rpcsvc/yp.x +++ b/c/src/exec/librpc/include/rpcsvc/yp.x @@ -0,0 +1,379 @@ +/* @(#)yp.x 2.1 88/08/01 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. + * + * 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 + */ + +/* + * Protocol description file for the Yellow Pages Service + */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/yp.x,v 1.12 1999/08/27 23:45:12 peter Exp $"; +%#endif /* not lint */ +#endif + +const YPMAXRECORD = 1024; +const YPMAXDOMAIN = 64; +const YPMAXMAP = 64; +const YPMAXPEER = 64; + + +enum ypstat { + YP_TRUE = 1, + YP_NOMORE = 2, + YP_FALSE = 0, + YP_NOMAP = -1, + YP_NODOM = -2, + YP_NOKEY = -3, + YP_BADOP = -4, + YP_BADDB = -5, + YP_YPERR = -6, + YP_BADARGS = -7, + YP_VERS = -8 +}; + + +enum ypxfrstat { + YPXFR_SUCC = 1, + YPXFR_AGE = 2, + YPXFR_NOMAP = -1, + YPXFR_NODOM = -2, + YPXFR_RSRC = -3, + YPXFR_RPC = -4, + YPXFR_MADDR = -5, + YPXFR_YPERR = -6, + YPXFR_BADARGS = -7, + YPXFR_DBM = -8, + YPXFR_FILE = -9, + YPXFR_SKEW = -10, + YPXFR_CLEAR = -11, + YPXFR_FORCE = -12, + YPXFR_XFRERR = -13, + YPXFR_REFUSED = -14 +}; + + +typedef string domainname; +typedef string mapname; +typedef string peername; +typedef opaque keydat; +typedef opaque valdat; + + +struct ypmap_parms { + domainname domain; + mapname map; + unsigned int ordernum; + peername peer; +}; + +struct ypreq_key { + domainname domain; + mapname map; + keydat key; +}; + +struct ypreq_nokey { + domainname domain; + mapname map; +}; + +struct ypreq_xfr { + ypmap_parms map_parms; + unsigned int transid; + unsigned int prog; + unsigned int port; +}; + + +struct ypresp_val { + ypstat stat; + valdat val; +}; + +struct ypresp_key_val { + ypstat stat; +#ifdef STUPID_SUN_BUG /* These are backwards */ + keydat key; + valdat val; +#else + valdat val; + keydat key; +#endif +}; + + +struct ypresp_master { + ypstat stat; + peername peer; +}; + +struct ypresp_order { + ypstat stat; + unsigned int ordernum; +}; + +union ypresp_all switch (bool more) { +case TRUE: + ypresp_key_val val; +case FALSE: + void; +}; + +struct ypresp_xfr { + unsigned int transid; + ypxfrstat xfrstat; +}; + +struct ypmaplist { + mapname map; + ypmaplist *next; +}; + +struct ypresp_maplist { + ypstat stat; + ypmaplist *maps; +}; + +enum yppush_status { + YPPUSH_SUCC = 1, /* Success */ + YPPUSH_AGE = 2, /* Master's version not newer */ + YPPUSH_NOMAP = -1, /* Can't find server for map */ + YPPUSH_NODOM = -2, /* Domain not supported */ + YPPUSH_RSRC = -3, /* Local resource alloc failure */ + YPPUSH_RPC = -4, /* RPC failure talking to server */ + YPPUSH_MADDR = -5, /* Can't get master address */ + YPPUSH_YPERR = -6, /* YP server/map db error */ + YPPUSH_BADARGS = -7, /* Request arguments bad */ + YPPUSH_DBM = -8, /* Local dbm operation failed */ + YPPUSH_FILE = -9, /* Local file I/O operation failed */ + YPPUSH_SKEW = -10, /* Map version skew during transfer */ + YPPUSH_CLEAR = -11, /* Can't send "Clear" req to local ypserv */ + YPPUSH_FORCE = -12, /* No local order number in map use -f flag. */ + YPPUSH_XFRERR = -13, /* ypxfr error */ + YPPUSH_REFUSED = -14 /* Transfer request refused by ypserv */ +}; + +struct yppushresp_xfr { + unsigned transid; + yppush_status status; +}; + +/* + * Response structure and overall result status codes. Success and failure + * represent two separate response message types. + */ + +enum ypbind_resptype { + YPBIND_SUCC_VAL = 1, + YPBIND_FAIL_VAL = 2 +}; + +struct ypbind_binding { + opaque ypbind_binding_addr[4]; /* In network order */ + opaque ypbind_binding_port[2]; /* In network order */ +}; + +union ypbind_resp switch (ypbind_resptype ypbind_status) { +case YPBIND_FAIL_VAL: + unsigned ypbind_error; +case YPBIND_SUCC_VAL: + ypbind_binding ypbind_bindinfo; +}; + +/* Detailed failure reason codes for response field ypbind_error*/ + +const YPBIND_ERR_ERR = 1; /* Internal error */ +const YPBIND_ERR_NOSERV = 2; /* No bound server for passed domain */ +const YPBIND_ERR_RESC = 3; /* System resource allocation failure */ + + +/* + * Request data structure for ypbind "Set domain" procedure. + */ +struct ypbind_setdom { + domainname ypsetdom_domain; + ypbind_binding ypsetdom_binding; + unsigned ypsetdom_vers; +}; + + +/* + * NIS v1 support for backwards compatibility + */ +enum ypreqtype { + YPREQ_KEY = 1, + YPREQ_NOKEY = 2, + YPREQ_MAP_PARMS = 3 +}; + +enum ypresptype { + YPRESP_VAL = 1, + YPRESP_KEY_VAL = 2, + YPRESP_MAP_PARMS = 3 +}; + +union yprequest switch (ypreqtype yp_reqtype) { +case YPREQ_KEY: + ypreq_key yp_req_keytype; +case YPREQ_NOKEY: + ypreq_nokey yp_req_nokeytype; +case YPREQ_MAP_PARMS: + ypmap_parms yp_req_map_parmstype; +}; + +union ypresponse switch (ypresptype yp_resptype) { +case YPRESP_VAL: + ypresp_val yp_resp_valtype; +case YPRESP_KEY_VAL: + ypresp_key_val yp_resp_key_valtype; +case YPRESP_MAP_PARMS: + ypmap_parms yp_resp_map_parmstype; +}; + +#if !defined(YPBIND_ONLY) && !defined(YPPUSH_ONLY) +/* + * YP access protocol + */ +program YPPROG { +/* + * NIS v1 support for backwards compatibility + */ + version YPOLDVERS { + void + YPOLDPROC_NULL(void) = 0; + + bool + YPOLDPROC_DOMAIN(domainname) = 1; + + bool + YPOLDPROC_DOMAIN_NONACK(domainname) = 2; + + ypresponse + YPOLDPROC_MATCH(yprequest) = 3; + + ypresponse + YPOLDPROC_FIRST(yprequest) = 4; + + ypresponse + YPOLDPROC_NEXT(yprequest) = 5; + + ypresponse + YPOLDPROC_POLL(yprequest) = 6; + + ypresponse + YPOLDPROC_PUSH(yprequest) = 7; + + ypresponse + YPOLDPROC_PULL(yprequest) = 8; + + ypresponse + YPOLDPROC_GET(yprequest) = 9; + } = 1; + + version YPVERS { + void + YPPROC_NULL(void) = 0; + + bool + YPPROC_DOMAIN(domainname) = 1; + + bool + YPPROC_DOMAIN_NONACK(domainname) = 2; + + ypresp_val + YPPROC_MATCH(ypreq_key) = 3; + + ypresp_key_val +#ifdef STUPID_SUN_BUG /* should be ypreq_nokey */ + YPPROC_FIRST(ypreq_key) = 4; +#else + YPPROC_FIRST(ypreq_nokey) = 4; +#endif + ypresp_key_val + YPPROC_NEXT(ypreq_key) = 5; + + ypresp_xfr + YPPROC_XFR(ypreq_xfr) = 6; + + void + YPPROC_CLEAR(void) = 7; + + ypresp_all + YPPROC_ALL(ypreq_nokey) = 8; + + ypresp_master + YPPROC_MASTER(ypreq_nokey) = 9; + + ypresp_order + YPPROC_ORDER(ypreq_nokey) = 10; + + ypresp_maplist + YPPROC_MAPLIST(domainname) = 11; + } = 2; +} = 100004; +#endif +#if !defined(YPSERV_ONLY) && !defined(YPBIND_ONLY) +/* + * YPPUSHPROC_XFRRESP is the callback routine for result of YPPROC_XFR + */ +program YPPUSH_XFRRESPPROG { + version YPPUSH_XFRRESPVERS { + void + YPPUSHPROC_NULL(void) = 0; +#ifdef STUPID_SUN_BUG /* argument and return value are backwards */ + yppushresp_xfr + YPPUSHPROC_XFRRESP(void) = 1; +#else + void + YPPUSHPROC_XFRRESP(yppushresp_xfr) = 1; +#endif + } = 1; +} = 0x40000000; /* transient: could be anything up to 0x5fffffff */ +#endif +#if !defined(YPSERV_ONLY) && !defined(YPPUSH_ONLY) +/* + * YP binding protocol + */ +program YPBINDPROG { + version YPBINDVERS { + void + YPBINDPROC_NULL(void) = 0; + + ypbind_resp + YPBINDPROC_DOMAIN(domainname) = 1; + + void + YPBINDPROC_SETDOM(ypbind_setdom) = 2; + } = 2; +} = 100007; + +#endif diff --git a/c/src/exec/librpc/include/rpcsvc/yp_prot.h b/c/src/exec/librpc/include/rpcsvc/yp_prot.h index e69de29bb2..92de593611 100644 --- a/c/src/exec/librpc/include/rpcsvc/yp_prot.h +++ b/c/src/exec/librpc/include/rpcsvc/yp_prot.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1992/3 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/rpcsvc/yp_prot.h,v 1.10 1999/08/27 23:45:12 peter Exp $ + */ + +#ifndef _RPCSVC_YP_PROT_H_ +#define _RPCSVC_YP_PROT_H_ + +/* + * YPSERV PROTOCOL: + * + * ypserv supports the following procedures: + * + * YPPROC_NULL takes (void), returns (void). + * called to check if server is alive. + * YPPROC_DOMAIN takes (char *), returns (bool_t). + * true if ypserv serves the named domain. + * YPPROC_DOMAIN_NOACK takes (char *), returns (bool_t). + * true if ypserv serves the named domain. + * used for broadcasts, does not ack if ypserv + * doesn't handle named domain. + * YPPROC_MATCH takes (struct ypreq_key), returns (struct ypresp_val) + * does a lookup. + * YPPROC_FIRST takes (struct ypreq_nokey) returns (ypresp_key_val). + * gets the first key/datum from the map. + * YPPROC_NEXT takes (struct ypreq_key) returns (ypresp_key_val). + * gets the next key/datum from the map. + * YPPROC_XFR takes (struct ypreq_xfr), returns (void). + * tells ypserv to check if there is a new version of + * the map. + * YPPROC_CLEAR takes (void), returns (void). + * tells ypserv to flush it's file cache, so that + * newly transferred files will get read. + * YPPROC_ALL takes (struct ypreq_nokey), returns (bool_t and + * struct ypresp_key_val). + * returns an array of data, with the bool_t being + * false on the last datum. read the source, it's + * convoluted. + * YPPROC_MASTER takes (struct ypreq_nokey), returns (ypresp_master). + * YPPROC_ORDER takes (struct ypreq_nokey), returns (ypresp_order). + * YPPROC_MAPLIST takes (char *), returns (struct ypmaplist *). + */ + +#ifndef BOOL_DEFINED +typedef u_int bool; +#define BOOL_DEFINED +#endif + +/* Program and version symbols, magic numbers */ + +#define YPPROG ((u_long)100004) +#define YPVERS ((u_long)2) +#define YPVERS_ORIG ((u_long)1) +#define YPMAXRECORD ((u_long)1024) +#define YPMAXDOMAIN ((u_long)64) +#define YPMAXMAP ((u_long)64) +#define YPMAXPEER ((u_long)256) + +/* + * I don't know if anything of sun's depends on this, or if they + * simply defined it so that their own code wouldn't try to send + * packets over the ethernet MTU. This YP code doesn't use it. + */ +#define YPMSGSZ 1600 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +struct ypmap_parms { + char *domain; + char *map; + u_long ordernum; + char *owner; +}; + +struct ypreq_key { + char *domain; + char *map; + datum keydat; +}; + +struct ypreq_nokey { + char *domain; + char *map; +}; + +struct ypreq_xfr { + struct ypmap_parms map_parms; + u_long transid; + u_long proto; + u_short port; +}; +#define ypxfr_domain map_parms.domain +#define ypxfr_map map_parms.map +#define ypxfr_ordernum map_parms.ordernum +#define ypxfr_owner map_parms.owner + +struct ypresp_val { + u_long status; + datum valdat; +}; + +struct ypresp_key_val { + u_long status; + datum keydat; + datum valdat; +}; + +struct ypresp_master { + u_long status; + char *master; +}; + +struct ypresp_order { + u_long status; + u_long ordernum; +}; + +struct ypmaplist { + char ypml_name[YPMAXMAP + 1]; + struct ypmaplist *ypml_next; +}; + +struct ypresp_maplist { + u_long status; + struct ypmaplist *list; +}; + +/* ypserv procedure numbers */ +#define YPPROC_NULL ((u_long)0) +#define YPPROC_DOMAIN ((u_long)1) +#define YPPROC_DOMAIN_NONACK ((u_long)2) +#define YPPROC_MATCH ((u_long)3) +#define YPPROC_FIRST ((u_long)4) +#define YPPROC_NEXT ((u_long)5) +#define YPPROC_XFR ((u_long)6) +#define YPPROC_CLEAR ((u_long)7) +#define YPPROC_ALL ((u_long)8) +#define YPPROC_MASTER ((u_long)9) +#define YPPROC_ORDER ((u_long)10) +#define YPPROC_MAPLIST ((u_long)11) + +/* ypserv procedure return status values */ +#define YP_TRUE ((long)1) /* general purpose success code */ +#define YP_NOMORE ((long)2) /* no more entries in map */ +#define YP_FALSE ((long)0) /* general purpose failure code */ +#define YP_NOMAP ((long)-1) /* no such map in domain */ +#define YP_NODOM ((long)-2) /* domain not supported */ +#define YP_NOKEY ((long)-3) /* no such key in map */ +#define YP_BADOP ((long)-4) /* invalid operation */ +#define YP_BADDB ((long)-5) /* server data base is bad */ +#define YP_YPERR ((long)-6) /* YP server error */ +#define YP_BADARGS ((long)-7) /* request arguments bad */ +#define YP_VERS ((long)-8) /* YP server version mismatch */ + +/* + * Sun's header file says: + * "Domain binding data structure, used by ypclnt package and ypserv modules. + * Users of the ypclnt package (or of this protocol) don't HAVE to know about + * it, but it must be available to users because _yp_dobind is a public + * interface." + * + * This is totally bogus! Nowhere else does Sun state that _yp_dobind() is + * a public interface, and I don't know any reason anyone would want to call + * it. But, just in case anyone does actually expect it to be available.. + * we provide this.. exactly as Sun wants it. + */ +struct dom_binding { + struct dom_binding *dom_pnext; + char dom_domain[YPMAXDOMAIN + 1]; + struct sockaddr_in dom_server_addr; + u_short dom_server_port; + int dom_socket; + CLIENT *dom_client; + u_short dom_local_port; + long dom_vers; +}; + +/* + * YPBIND PROTOCOL: + * + * ypbind supports the following procedures: + * + * YPBINDPROC_NULL takes (void), returns (void). + * to check if ypbind is running. + * YPBINDPROC_DOMAIN takes (char *), returns (struct ypbind_resp). + * requests that ypbind start to serve the + * named domain (if it doesn't already) + * YPBINDPROC_SETDOM takes (struct ypbind_setdom), returns (void). + * used by ypset. + */ + +#define YPBINDPROG ((u_long)100007) +#define YPBINDVERS ((u_long)2) +#define YPBINDVERS_ORIG ((u_long)1) + +/* ypbind procedure numbers */ +#define YPBINDPROC_NULL ((u_long)0) +#define YPBINDPROC_DOMAIN ((u_long)1) +#define YPBINDPROC_SETDOM ((u_long)2) + +/* error code in ypbind_resp.ypbind_status */ +enum ypbind_resptype { + YPBIND_SUCC_VAL = 1, + YPBIND_FAIL_VAL = 2 +}; + +/* network order, of course */ +struct ypbind_binding { + struct in_addr ypbind_binding_addr; + u_short ypbind_binding_port; +}; + +struct ypbind_resp { + enum ypbind_resptype ypbind_status; + union { + u_long ypbind_error; + struct ypbind_binding ypbind_bindinfo; + } ypbind_respbody; +}; + +/* error code in ypbind_resp.ypbind_respbody.ypbind_error */ +#define YPBIND_ERR_ERR 1 /* internal error */ +#define YPBIND_ERR_NOSERV 2 /* no bound server for passed domain */ +#define YPBIND_ERR_RESC 3 /* system resource allocation failure */ + +/* + * Request data structure for ypbind "Set domain" procedure. + */ +struct ypbind_setdom { + char ypsetdom_domain[YPMAXDOMAIN + 1]; + struct ypbind_binding ypsetdom_binding; + u_short ypsetdom_vers; +}; +#define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr +#define ypsetdom_port ypsetdom_binding.ypbind_binding_port + +/* + * YPPUSH PROTOCOL: + * + * Sun says: + * "Protocol between clients (ypxfr, only) and yppush + * yppush speaks a protocol in the transient range, which + * is supplied to ypxfr as a command-line parameter when it + * is activated by ypserv." + * + * This protocol is not implemented, naturally, because this YP + * implementation only does the client side. + */ +#define YPPUSHVERS ((u_long)1) +#define YPPUSHVERS_ORIG ((u_long)1) + +/* yppush procedure numbers */ +#define YPPUSHPROC_NULL ((u_long)0) +#define YPPUSHPROC_XFRRESP ((u_long)1) + +struct yppushresp_xfr { + u_long transid; + u_long status; +}; + +/* yppush status value in yppushresp_xfr.status */ +#define YPPUSH_SUCC ((long)1) /* Success */ +#define YPPUSH_AGE ((long)2) /* Master's version not newer */ +#define YPPUSH_NOMAP ((long)-1) /* Can't find server for map */ +#define YPPUSH_NODOM ((long)-2) /* Domain not supported */ +#define YPPUSH_RSRC ((long)-3) /* Local resource alloc failure */ +#define YPPUSH_RPC ((long)-4) /* RPC failure talking to server */ +#define YPPUSH_MADDR ((long)-5) /* Can't get master address */ +#define YPPUSH_YPERR ((long)-6) /* YP server/map db error */ +#define YPPUSH_BADARGS ((long)-7) /* Request arguments bad */ +#define YPPUSH_DBM ((long)-8) /* Local dbm operation failed */ +#define YPPUSH_FILE ((long)-9) /* Local file I/O operation failed */ +#define YPPUSH_SKEW ((long)-10) /* Map version skew during transfer */ +#define YPPUSH_CLEAR ((long)-11) /* Can't send "Clear" req to local ypserv */ +#define YPPUSH_FORCE ((long)-12) /* No local order number in map - use -f */ +#define YPPUSH_XFRERR ((long)-13) /* ypxfr error */ +#define YPPUSH_REFUSED ((long)-14) /* Transfer request refused by ypserv */ + +struct inaddr; +__BEGIN_DECLS +bool_t xdr_datum __P((XDR *, datum *)); +bool_t xdr_ypreq_key __P((XDR *, struct ypreq_key *)); +bool_t xdr_ypreq_nokey __P((XDR *, struct ypreq_nokey *)); +bool_t xdr_ypreq_xfr __P((XDR *, struct ypreq_xfr *)); +bool_t xdr_ypresp_val __P((XDR *, struct ypresp_val *)); +bool_t xdr_ypresp_key_val __P((XDR *, struct ypresp_key_val *)); +bool_t xdr_ypbind_resp __P((XDR *, struct ypbind_resp *)); +bool_t xdr_ypbind_setdom __P((XDR *, struct ypbind_setdom *)); +bool_t xdr_yp_inaddr __P((XDR *, struct inaddr *)); +bool_t xdr_ypmap_parms __P((XDR *, struct ypmap_parms *)); +bool_t xdr_yppushresp_xfr __P((XDR *, struct yppushresp_xfr *)); +bool_t xdr_ypresp_order __P((XDR *, struct ypresp_order *)); +bool_t xdr_ypresp_master __P((XDR *, struct ypresp_master *)); +bool_t xdr_ypresp_maplist __P((XDR *, struct ypresp_maplist *)); +__END_DECLS + +#endif /* _RPCSVC_YP_PROT_H_ */ diff --git a/c/src/exec/librpc/include/rpcsvc/ypclnt.h b/c/src/exec/librpc/include/rpcsvc/ypclnt.h index e69de29bb2..9636ba2d84 100644 --- a/c/src/exec/librpc/include/rpcsvc/ypclnt.h +++ b/c/src/exec/librpc/include/rpcsvc/ypclnt.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1992/3 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/rpcsvc/ypclnt.h,v 1.11 1999/08/27 23:45:12 peter Exp $ + */ + +#ifndef _RPCSVC_YPCLNT_H_ +#define _RPCSVC_YPCLNT_H_ + +#include + +#define YPERR_BADARGS 1 /* args to function are bad */ +#define YPERR_RPC 2 /* RPC failure */ +#define YPERR_DOMAIN 3 /* can't bind to a server for domain */ +#define YPERR_MAP 4 /* no such map in server's domain */ +#define YPERR_KEY 5 /* no such key in map */ +#define YPERR_YPERR 6 /* some internal YP server or client error */ +#define YPERR_RESRC 7 /* local resource allocation failure */ +#define YPERR_NOMORE 8 /* no more records in map database */ +#define YPERR_PMAP 9 /* can't communicate with portmapper */ +#define YPERR_YPBIND 10 /* can't communicate with ypbind */ +#define YPERR_YPSERV 11 /* can't communicate with ypserv */ +#define YPERR_NODOM 12 /* local domain name not set */ +#define YPERR_BADDB 13 /* YP data base is bad */ +#define YPERR_VERS 14 /* YP version mismatch */ +#define YPERR_ACCESS 15 /* access violation */ +#define YPERR_BUSY 16 /* database is busy */ + +/* + * Types of update operations + */ +#define YPOP_CHANGE 1 /* change, do not add */ +#define YPOP_INSERT 2 /* add, do not change */ +#define YPOP_DELETE 3 /* delete this entry */ +#define YPOP_STORE 4 /* add, or change */ + +struct ypall_callback { + /* return non-0 to stop getting called */ + int (*foreach) __P((unsigned long, char *, int, char *, int, void *)); + char *data; /* opaque pointer for use of callback fn */ +}; + +struct dom_binding; + +__BEGIN_DECLS +int yp_bind __P((char *dom)); +int _yp_dobind __P((char *dom, struct dom_binding **ypdb)); +void yp_unbind __P((char *dom)); +int yp_get_default_domain __P((char **domp)); +int yp_match __P((char *indomain, char *inmap, + const char *inkey, int inkeylen, char **outval, + int *outvallen)); +int yp_first __P((char *indomain, char *inmap, + char **outkey, int *outkeylen, char **outval, + int *outvallen)); +int yp_next __P((char *indomain, char *inmap, + char *inkey, int inkeylen, char **outkey, + int *outkeylen, char **outval, int *outvallen)); +int yp_master __P((char *indomain, char *inmap, char **outname)); +int yp_order __P((char *indomain, char *inmap, int *outorder)); +int yp_all __P((char *indomain, char *inmap, + struct ypall_callback *incallback)); +char * yperr_string __P((int incode)); +char * ypbinderr_string __P((int incode)); +int ypprot_err __P((unsigned int incode)); +__END_DECLS + +#endif /* _RPCSVC_YPCLNT_H_ */ + diff --git a/c/src/exec/librpc/include/rpcsvc/yppasswd.x b/c/src/exec/librpc/include/rpcsvc/yppasswd.x index e69de29bb2..bcc83a1346 100644 --- a/c/src/exec/librpc/include/rpcsvc/yppasswd.x +++ b/c/src/exec/librpc/include/rpcsvc/yppasswd.x @@ -0,0 +1,75 @@ +/* + * 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 + */ + +/* + * YP password update protocol + * Requires unix authentication + */ + +#ifndef RPC_HDR +%#ifndef lint +%/*static char sccsid[] = "from: @(#)yppasswd.x 1.1 87/04/13 Copyr 1987 Sun Micro";*/ +%/*static char sccsid[] = "from: @(#)yppasswd.x 2.1 88/08/01 4.0 RPCSRC";*/ +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/yppasswd.x,v 1.6 1999/08/27 23:45:12 peter Exp $"; +%#endif /* not lint */ +#endif + +program YPPASSWDPROG { + version YPPASSWDVERS { + /* + * Update my passwd entry + */ + int + YPPASSWDPROC_UPDATE(yppasswd) = 1; + } = 1; +} = 100009; + + +struct x_passwd { + string pw_name<>; /* username */ + string pw_passwd<>; /* encrypted password */ + int pw_uid; /* user id */ + int pw_gid; /* group id */ + string pw_gecos<>; /* in real life name */ + string pw_dir<>; /* home directory */ + string pw_shell<>; /* default shell */ +}; + +struct yppasswd { + string oldpass<>; /* unencrypted old password */ + x_passwd newpw; /* new passwd entry */ +}; + + +#ifdef RPC_HDR +%#include +%extern int _yppasswd __P(( char * , struct x_passwd * )); +%#define yppasswd(x,y) _yppasswd(x,y) +#endif diff --git a/c/src/exec/librpc/include/rpcsvc/ypupdate_prot.x b/c/src/exec/librpc/include/rpcsvc/ypupdate_prot.x index e69de29bb2..f16d5ee45e 100644 --- a/c/src/exec/librpc/include/rpcsvc/ypupdate_prot.x +++ b/c/src/exec/librpc/include/rpcsvc/ypupdate_prot.x @@ -0,0 +1,88 @@ +%/* +% * 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 +% */ + +%/* +% * Copyright (c) 1986, 1990 by Sun Microsystems, Inc. +% */ +% +%/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */ +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/ypupdate_prot.x,v 1.3 1999/08/27 23:45:13 peter Exp $"; +%#endif +#endif +% +%/* +% * Compiled from ypupdate_prot.x using rpcgen +% * This is NOT source code! +% * DO NOT EDIT THIS FILE! +% */ + +/* + * YP update service protocol + */ +#ifdef RPC_HDR +% +%#ifndef _rpcsvc_ypupdate_prot_h +%#define _rpcsvc_ypupdate_prot_h +% +#endif + +const MAXMAPNAMELEN = 255; +const MAXYPDATALEN = 1023; +const MAXERRMSGLEN = 255; + +program YPU_PROG { + version YPU_VERS { + u_int YPU_CHANGE(ypupdate_args) = 1; + u_int YPU_INSERT(ypupdate_args) = 2; + u_int YPU_DELETE(ypdelete_args) = 3; + u_int YPU_STORE(ypupdate_args) = 4; + } = 1; +} = 100028; + +typedef opaque yp_buf; + +struct ypupdate_args { + string mapname; + yp_buf key; + yp_buf datum; +}; + +struct ypdelete_args { + string mapname; + yp_buf key; +}; + +#ifdef RPC_HDR +% +%#endif /* !_rpcsvc_ypupdate_prot_h */ +#endif diff --git a/c/src/exec/librpc/include/rpcsvc/ypxfrd.x b/c/src/exec/librpc/include/rpcsvc/ypxfrd.x index e69de29bb2..1845a4f43b 100644 --- a/c/src/exec/librpc/include/rpcsvc/ypxfrd.x +++ b/c/src/exec/librpc/include/rpcsvc/ypxfrd.x @@ -0,0 +1,173 @@ +/* + * Copyright (c) 1995, 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/include/rpcsvc/ypxfrd.x,v 1.7 1999/08/27 23:45:13 peter Exp $ + */ + +/* + * This protocol definition file describes a file transfer + * system used to very quickly move NIS maps from one host to + * another. This is similar to what Sun does with their ypxfrd + * protocol, but it must be stressed that this protocol is _NOT_ + * compatible with Sun's. There are a couple of reasons for this: + * + * 1) Sun's protocol is proprietary. The protocol definition is + * not freely available in any of the SunRPC source distributions, + * even though the NIS v2 protocol is. + * + * 2) The idea here is to transfer entire raw files rather than + * sending just the records. Sun uses ndbm for its NIS map files, + * while FreeBSD uses Berkeley DB. Both are hash databases, but the + * formats are incompatible, making it impossible for them to + * use each others' files. Even if FreeBSD adopted ndbm for its + * database format, FreeBSD/i386 is a little-endian OS and + * SunOS/SPARC is big-endian; ndbm is byte-order sensitive and + * not very smart about it, which means an attempt to read a + * database on a little-endian box that was created on a big-endian + * box (or vice-versa) can cause the ndbm code to eat itself. + * Luckily, Berkeley DB is able to deal with this situation in + * a more graceful manner. + * + * While the protocol is incompatible, the idea is the same: we just open + * up a TCP pipe to the client and transfer the raw map database + * from the master server to the slave. This is many times faster than + * the standard yppush/ypxfr transfer method since it saves us from + * having to recreate the map databases via the DB library each time. + * For example: creating a passwd database with 30,000 entries with yp_mkdb + * can take a couple of minutes, but to just copy the file takes only a few + * seconds. + */ + +#ifndef RPC_HDR +%#ifndef lint +%static const char rcsid[] = +% "$FreeBSD: src/include/rpcsvc/ypxfrd.x,v 1.7 1999/08/27 23:45:13 peter Exp $"; +%#endif /* not lint */ +#endif + +/* XXX cribbed from yp.x */ +const _YPMAXRECORD = 1024; +const _YPMAXDOMAIN = 64; +const _YPMAXMAP = 64; +const _YPMAXPEER = 64; + +/* Suggested default -- not necesarrily the one used. */ +const YPXFRBLOCK = 32767; + +/* + * Possible return codes from the remote server. + */ +enum xfrstat { + XFR_REQUEST_OK = 1, /* Transfer request granted */ + XFR_DENIED = 2, /* Transfer request denied */ + XFR_NOFILE = 3, /* Requested map file doesn't exist */ + XFR_ACCESS = 4, /* File exists, but I couldn't access it */ + XFR_BADDB = 5, /* File is not a hash database */ + XFR_READ_OK = 6, /* Block read successfully */ + XFR_READ_ERR = 7, /* Read error during transfer */ + XFR_DONE = 8, /* Transfer completed */ + XFR_DB_ENDIAN_MISMATCH = 9, /* Database byte order mismatch */ + XFR_DB_TYPE_MISMATCH = 10 /* Database type mismatch */ +}; + +/* + * Database type specifications. The client can use this to ask + * the server for a particular type of database or just take whatever + * the server has to offer. + */ +enum xfr_db_type { + XFR_DB_ASCII = 1, /* Flat ASCII text */ + XFR_DB_BSD_HASH = 2, /* Berkeley DB, hash method */ + XFR_DB_BSD_BTREE = 3, /* Berkeley DB, btree method */ + XFR_DB_BSD_RECNO = 4, /* Berkeley DB, recno method */ + XFR_DB_BSD_MPOOL = 5, /* Berkeley DB, mpool method */ + XFR_DB_BSD_NDBM = 6, /* Berkeley DB, hash, ndbm compat */ + XFR_DB_GNU_GDBM = 7, /* GNU GDBM */ + XFR_DB_DBM = 8, /* Old, deprecated dbm format */ + XFR_DB_NDBM = 9, /* ndbm format (used by Sun's NISv2) */ + XFR_DB_OPAQUE = 10, /* Mystery format -- just pass along */ + XFR_DB_ANY = 11, /* I'll take any format you've got */ + XFR_DB_UNKNOWN = 12 /* Unknown format */ +}; + +/* + * Machine byte order specification. This allows the client to check + * that it's copying a map database from a machine of similar byte sex. + * This is necessary for handling database libraries that are fatally + * byte order sensitive. + * + * The XFR_ENDIAN_ANY type is for use with the Berkeley DB database + * formats; Berkeley DB is smart enough to make up for byte order + * differences, so byte sex isn't important. + */ +enum xfr_byte_order { + XFR_ENDIAN_BIG = 1, /* We want big endian */ + XFR_ENDIAN_LITTLE = 2, /* We want little endian */ + XFR_ENDIAN_ANY = 3 /* We'll take whatever you got */ +}; + +typedef string xfrdomain<_YPMAXDOMAIN>; +typedef string xfrmap<_YPMAXMAP>; +typedef string xfrmap_filename<_YPMAXMAP>; /* actual name of map file */ + +/* + * Ask the remote ypxfrd for a map using this structure. + * Note: we supply both a map name and a map file name. These are not + * the same thing. In the case of ndbm, maps are stored in two files: + * map.bykey.pag and may.bykey.dir. We may also have to deal with + * file extensions (on the off chance that the remote server is supporting + * multiple DB formats). To handle this, we tell the remote server both + * what map we want and, in the case of ndbm, whether we want the .dir + * or the .pag part. This name should not be a fully qualified path: + * it's up to the remote server to decide which directories to look in. + */ +struct ypxfr_mapname { + xfrmap xfrmap; + xfrdomain xfrdomain; + xfrmap_filename xfrmap_filename; + xfr_db_type xfr_db_type; + xfr_byte_order xfr_byte_order; +}; + +/* Read response using this structure. */ +union xfr switch (bool ok) { +case TRUE: + opaque xfrblock_buf<>; +case FALSE: + xfrstat xfrstat; +}; + +program YPXFRD_FREEBSD_PROG { + version YPXFRD_FREEBSD_VERS { + union xfr + YPXFRD_GETMAP(ypxfr_mapname) = 1; + } = 1; +} = 600100069; /* 100069 + 60000000 -- 100069 is the Sun ypxfrd prog number */ diff --git a/c/src/exec/librpc/src/Makefile.am b/c/src/exec/librpc/src/Makefile.am index efa6a1cadb..8a1c7a987b 100644 --- a/c/src/exec/librpc/src/Makefile.am +++ b/c/src/exec/librpc/src/Makefile.am @@ -1,35 +1,10 @@ ## -## $Id$ +## $Id$ ## AUTOMAKE_OPTIONS = foreign 1.4 -LIBNAME = librpc -LIB = ${ARCH}/${LIBNAME}.a - -C_FILES = rpc_callmsg.c rpc_prot.c svc.c svc_auth.c svc_udp.c xdr.c \ - xdr_array.c xdr_mem.c -C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o) - -SRCS = $(C_FILES) -OBJS = $(C_O_FILES) - -include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg -include $(top_srcdir)/../../../automake/lib.am - -AM_CFLAGS += $(LIBC_DEFINES) - -TMPINSTALL_FILES += \ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a - -$(LIB): ${OBJS} - $(make-library) - -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) - $(INSTALL_DATA) $< $@ - -all: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES) - -EXTRA_DIST = $(C_FILES) +SUBDIRS = xdr rpc +include $(top_srcdir)/../../../automake/subdirs.am include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/src/rpc/DISCLAIMER b/c/src/exec/librpc/src/rpc/DISCLAIMER index e69de29bb2..1a66d5f4c9 100644 --- a/c/src/exec/librpc/src/rpc/DISCLAIMER +++ b/c/src/exec/librpc/src/rpc/DISCLAIMER @@ -0,0 +1,28 @@ +/* + * 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 + */ diff --git a/c/src/exec/librpc/src/rpc/Makefile.am b/c/src/exec/librpc/src/rpc/Makefile.am index e69de29bb2..1c7542fb1b 100644 --- a/c/src/exec/librpc/src/rpc/Makefile.am +++ b/c/src/exec/librpc/src/rpc/Makefile.am @@ -0,0 +1,57 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 no-installman + +SUBDIRS = PSD.doc + +LIBNAME = librpc +LIB = $(ARCH)/$(LIBNAME).a + +C_FILES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ + clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \ + clnt_udp.c get_myaddress.c getrpcent.c getrpcport.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_unix.c svc_raw.c svc_run.c \ + svc_simple.c svc_tcp.c svc_udp.c rtems_portmapper.c rtems_rpc.c +UNUSED_C_FILES = auth_des.c auth_time.c authdes_prot.c clnt_unix.c \ + crypt_client.c des_crypt.c des_soft.c getpublickey.c key_call.c \ + key_prot_xdr.c svc_auth_des.c svc_unix.c + +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../automake/lib.am + +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a + +# +# Add local stuff here using += +# + +AM_CPPFLAGS += '-D__P(x)=x' -D_read=read -D_write=write -D_close=close -D_RTEMS_RPC_INTERNAL_ + +$(LIB): $(OBJS) + $(make-library) + +$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) + $(INSTALL_DATA) $< $@ + +noinst_MANS = bindresvport.3 getrpcent.3 publickey.3 rpc.3 rpc_secure.3 \ + rstat_svc.8 des_crypt.3 getrpcport.3 publickey.5 rpc.5 rstat.1 rtime.3 + +if HAS_NETWORKING +man_MANS = $(noinst_MANS) +all-local: $(ARCH) $(OBJS) $(TMPINSTALL_FILES) +endif + +.PRECIOUS: $(LIB) + +EXTRA_DIST = $(C_FILES) DISCLAIMER $(UNUSED_C_FILES) $(noinst_MANS) + +include $(top_srcdir)/../../../automake/subdirs.am +include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/.cvsignore b/c/src/exec/librpc/src/rpc/PSD.doc/.cvsignore index e69de29bb2..282522db03 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/.cvsignore +++ b/c/src/exec/librpc/src/rpc/PSD.doc/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/Makefile.am b/c/src/exec/librpc/src/rpc/PSD.doc/Makefile.am index e69de29bb2..cd8172dbfd 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/Makefile.am +++ b/c/src/exec/librpc/src/rpc/PSD.doc/Makefile.am @@ -0,0 +1,8 @@ +## $Id$ + +AUTOMAKE_OPTIONS = foreign 1.4 + +EXTRA_DIST = nfs.rfc.ms rpc.prog.ms rpc.rfc.ms rpcgen.ms xdr.nts.ms \ + xdr.rfc.ms + +include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/nfs.rfc.ms b/c/src/exec/librpc/src/rpc/PSD.doc/nfs.rfc.ms index e69de29bb2..0c9a8995b5 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/nfs.rfc.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/nfs.rfc.ms @@ -0,0 +1,1372 @@ +.\" +.\" Must use -- tbl -- with this one +.\" +.\" @(#)nfs.rfc.ms 2.2 88/08/05 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'Network File System: Version 2 Protocol Specification''Page %' +.EH 'Page %''Network File System: Version 2 Protocol Specification' +.if \\n%=1 .bp +.SH +\&Network File System: Version 2 Protocol Specification +.IX NFS "" "" "" PAGE MAJOR +.IX "Network File System" "" "" "" PAGE MAJOR +.IX NFS "version-2 protocol specification" +.IX "Network File System" "version-2 protocol specification" +.LP +.NH 0 +\&Status of this Standard +.LP +Note: This document specifies a protocol that Sun Microsystems, Inc., +and others are using. It specifies it in standard ARPA RFC form. +.NH 1 +\&Introduction +.IX NFS introduction +.LP +The Sun Network Filesystem (NFS) protocol provides transparent remote +access to shared filesystems over local area networks. The NFS +protocol is designed to be machine, operating system, network architecture, +and transport protocol independent. This independence is +achieved through the use of Remote Procedure Call (RPC) primitives +built on top of an External Data Representation (XDR). Implementations +exist for a variety of machines, from personal computers to +supercomputers. +.LP +The supporting mount protocol allows the server to hand out remote +access privileges to a restricted set of clients. It performs the +operating system-specific functions that allow, for example, to +attach remote directory trees to some local file system. +.NH 2 +\&Remote Procedure Call +.IX "Remote Procedure Call" +.LP +Sun's remote procedure call specification provides a procedure- +oriented interface to remote services. Each server supplies a +program that is a set of procedures. NFS is one such "program". +The combination of host address, program number, and procedure +number specifies one remote service procedure. RPC does not depend +on services provided by specific protocols, so it can be used with +any underlying transport protocol. See the +.I "Remote Procedure Calls: Protocol Specification" +chapter of this manual. +.NH 2 +\&External Data Representation +.IX "External Data Representation" +.LP +The External Data Representation (XDR) standard provides a common +way of representing a set of data types over a network. +The NFS +Protocol Specification is written using the RPC data description +language. +For more information, see the +.I " External Data Representation Standard: Protocol Specification." +Sun provides implementations of XDR and +RPC, but NFS does not require their use. Any software that +provides equivalent functionality can be used, and if the encoding +is exactly the same it can interoperate with other implementations +of NFS. +.NH 2 +\&Stateless Servers +.IX "stateless servers" +.IX servers stateless +.LP +The NFS protocol is stateless. That is, a server does not need to +maintain any extra state information about any of its clients in +order to function correctly. Stateless servers have a distinct +advantage over stateful servers in the event of a failure. With +stateless servers, a client need only retry a request until the +server responds; it does not even need to know that the server has +crashed, or the network temporarily went down. The client of a +stateful server, on the other hand, needs to either detect a server +crash and rebuild the server's state when it comes back up, or +cause client operations to fail. +.LP +This may not sound like an important issue, but it affects the +protocol in some unexpected ways. We feel that it is worth a bit +of extra complexity in the protocol to be able to write very simple +servers that do not require fancy crash recovery. +.LP +On the other hand, NFS deals with objects such as files and +directories that inherently have state -- what good would a file be +if it did not keep its contents intact? The goal is to not +introduce any extra state in the protocol itself. Another way to +simplify recovery is by making operations "idempotent" whenever +possible (so that they can potentially be repeated). +.NH 1 +\&NFS Protocol Definition +.IX NFS "protocol definition" +.IX NFS protocol +.LP +Servers have been known to change over time, and so can the +protocol that they use. So RPC provides a version number with each +RPC request. This RFC describes version two of the NFS protocol. +Even in the second version, there are various obsolete procedures +and parameters, which will be removed in later versions. An RFC +for version three of the NFS protocol is currently under +preparation. +.NH 2 +\&File System Model +.IX filesystem model +.LP +NFS assumes a file system that is hierarchical, with directories as +all but the bottom-level files. Each entry in a directory (file, +directory, device, etc.) has a string name. Different operating +systems may have restrictions on the depth of the tree or the names +used, as well as using different syntax to represent the "pathname", +which is the concatenation of all the "components" (directory and +file names) in the name. A "file system" is a tree on a single +server (usually a single disk or physical partition) with a specified +"root". Some operating systems provide a "mount" operation to make +all file systems appear as a single tree, while others maintain a +"forest" of file systems. Files are unstructured streams of +uninterpreted bytes. Version 3 of NFS uses a slightly more general +file system model. +.LP +NFS looks up one component of a pathname at a time. It may not be +obvious why it does not just take the whole pathname, traipse down +the directories, and return a file handle when it is done. There are +several good reasons not to do this. First, pathnames need +separators between the directory components, and different operating +systems use different separators. We could define a Network Standard +Pathname Representation, but then every pathname would have to be +parsed and converted at each end. Other issues are discussed in +\fINFS Implementation Issues\fP below. +.LP +Although files and directories are similar objects in many ways, +different procedures are used to read directories and files. This +provides a network standard format for representing directories. The +same argument as above could have been used to justify a procedure +that returns only one directory entry per call. The problem is +efficiency. Directories can contain many entries, and a remote call +to return each would be just too slow. +.NH 2 +\&RPC Information +.IX NFS "RPC information" +.IP \fIAuthentication\fP +The NFS service uses +.I AUTH_UNIX , +.I AUTH_DES , +or +.I AUTH_SHORT +style +authentication, except in the NULL procedure where +.I AUTH_NONE +is also allowed. +.IP "\fITransport Protocols\fP" +NFS currently is supported on UDP/IP only. +.IP "\fIPort Number\fP" +The NFS protocol currently uses the UDP port number 2049. This is +not an officially assigned port, so later versions of the protocol +use the \*QPortmapping\*U facility of RPC. +.NH 2 +\&Sizes of XDR Structures +.IX "XDR structure sizes" +.LP +These are the sizes, given in decimal bytes, of various XDR +structures used in the protocol: +.DS +/* \fIThe maximum number of bytes of data in a READ or WRITE request\fP */ +const MAXDATA = 8192; + +/* \fIThe maximum number of bytes in a pathname argument\fP */ +const MAXPATHLEN = 1024; + +/* \fIThe maximum number of bytes in a file name argument\fP */ +const MAXNAMLEN = 255; + +/* \fIThe size in bytes of the opaque "cookie" passed by READDIR\fP */ +const COOKIESIZE = 4; + +/* \fIThe size in bytes of the opaque file handle\fP */ +const FHSIZE = 32; +.DE +.NH 2 +\&Basic Data Types +.IX "NFS data types" +.IX NFS "basic data types" +.LP +The following XDR definitions are basic structures and types used +in other structures described further on. +.KS +.NH 3 +\&stat +.IX "NFS data types" stat "" \fIstat\fP +.DS +enum stat { + NFS_OK = 0, + NFSERR_PERM=1, + NFSERR_NOENT=2, + NFSERR_IO=5, + NFSERR_NXIO=6, + NFSERR_ACCES=13, + NFSERR_EXIST=17, + NFSERR_NODEV=19, + NFSERR_NOTDIR=20, + NFSERR_ISDIR=21, + NFSERR_FBIG=27, + NFSERR_NOSPC=28, + NFSERR_ROFS=30, + NFSERR_NAMETOOLONG=63, + NFSERR_NOTEMPTY=66, + NFSERR_DQUOT=69, + NFSERR_STALE=70, + NFSERR_WFLUSH=99 +}; +.DE +.KE +.LP +The +.I stat +type is returned with every procedure's results. A +value of +.I NFS_OK +indicates that the call completed successfully and +the results are valid. The other values indicate some kind of +error occurred on the server side during the servicing of the +procedure. The error values are derived from UNIX error numbers. +.IP \fBNFSERR_PERM\fP: +Not owner. The caller does not have correct ownership +to perform the requested operation. +.IP \fBNFSERR_NOENT\fP: +No such file or directory. The file or directory +specified does not exist. +.IP \fBNFSERR_IO\fP: +Some sort of hard error occurred when the operation was +in progress. This could be a disk error, for example. +.IP \fBNFSERR_NXIO\fP: +No such device or address. +.IP \fBNFSERR_ACCES\fP: +Permission denied. The caller does not have the +correct permission to perform the requested operation. +.IP \fBNFSERR_EXIST\fP: +File exists. The file specified already exists. +.IP \fBNFSERR_NODEV\fP: +No such device. +.IP \fBNFSERR_NOTDIR\fP: +Not a directory. The caller specified a +non-directory in a directory operation. +.IP \fBNFSERR_ISDIR\fP: +Is a directory. The caller specified a directory in +a non- directory operation. +.IP \fBNFSERR_FBIG\fP: +File too large. The operation caused a file to grow +beyond the server's limit. +.IP \fBNFSERR_NOSPC\fP: +No space left on device. The operation caused the +server's filesystem to reach its limit. +.IP \fBNFSERR_ROFS\fP: +Read-only filesystem. Write attempted on a read-only filesystem. +.IP \fBNFSERR_NAMETOOLONG\fP: +File name too long. The file name in an operation was too long. +.IP \fBNFSERR_NOTEMPTY\fP: +Directory not empty. Attempted to remove a +directory that was not empty. +.IP \fBNFSERR_DQUOT\fP: +Disk quota exceeded. The client's disk quota on the +server has been exceeded. +.IP \fBNFSERR_STALE\fP: +The "fhandle" given in the arguments was invalid. +That is, the file referred to by that file handle no longer exists, +or access to it has been revoked. +.IP \fBNFSERR_WFLUSH\fP: +The server's write cache used in the +.I WRITECACHE +call got flushed to disk. +.LP +.KS +.NH 3 +\&ftype +.IX "NFS data types" ftype "" \fIftype\fP +.DS +enum ftype { + NFNON = 0, + NFREG = 1, + NFDIR = 2, + NFBLK = 3, + NFCHR = 4, + NFLNK = 5 +}; +.DE +.KE +The enumeration +.I ftype +gives the type of a file. The type +.I NFNON +indicates a non-file, +.I NFREG +is a regular file, +.I NFDIR +is a directory, +.I NFBLK +is a block-special device, +.I NFCHR +is a character-special device, and +.I NFLNK +is a symbolic link. +.KS +.NH 3 +\&fhandle +.IX "NFS data types" fhandle "" \fIfhandle\fP +.DS +typedef opaque fhandle[FHSIZE]; +.DE +.KE +The +.I fhandle +is the file handle passed between the server and the client. +All file operations are done using file handles to refer to a file or +directory. The file handle can contain whatever information the server +needs to distinguish an individual file. +.KS +.NH 3 +\&timeval +.IX "NFS data types" timeval "" \fItimeval\fP +.DS +struct timeval { + unsigned int seconds; + unsigned int useconds; +}; +.DE +.KE +The +.I timeval +structure is the number of seconds and microseconds +since midnight January 1, 1970, Greenwich Mean Time. It is used to +pass time and date information. +.KS +.NH 3 +\&fattr +.IX "NFS data types" fattr "" \fIfattr\fP +.DS +struct fattr { + ftype type; + unsigned int mode; + unsigned int nlink; + unsigned int uid; + unsigned int gid; + unsigned int size; + unsigned int blocksize; + unsigned int rdev; + unsigned int blocks; + unsigned int fsid; + unsigned int fileid; + timeval atime; + timeval mtime; + timeval ctime; +}; +.DE +.KE +The +.I fattr +structure contains the attributes of a file; "type" is the type of +the file; "nlink" is the number of hard links to the file (the number +of different names for the same file); "uid" is the user +identification number of the owner of the file; "gid" is the group +identification number of the group of the file; "size" is the size in +bytes of the file; "blocksize" is the size in bytes of a block of the +file; "rdev" is the device number of the file if it is type +.I NFCHR +or +.I NFBLK ; +"blocks" is the number of blocks the file takes up on disk; "fsid" is +the file system identifier for the filesystem containing the file; +"fileid" is a number that uniquely identifies the file within its +filesystem; "atime" is the time when the file was last accessed for +either read or write; "mtime" is the time when the file data was last +modified (written); and "ctime" is the time when the status of the +file was last changed. Writing to the file also changes "ctime" if +the size of the file changes. +.LP +"mode" is the access mode encoded as a set of bits. Notice that the +file type is specified both in the mode bits and in the file type. +This is really a bug in the protocol and will be fixed in future +versions. The descriptions given below specify the bit positions +using octal numbers. +.TS +box tab (&) ; +cfI cfI +lfL l . +Bit&Description +_ +0040000&This is a directory; "type" field should be NFDIR. +0020000&This is a character special file; "type" field should be NFCHR. +0060000&This is a block special file; "type" field should be NFBLK. +0100000&This is a regular file; "type" field should be NFREG. +0120000&This is a symbolic link file; "type" field should be NFLNK. +0140000&This is a named socket; "type" field should be NFNON. +0004000&Set user id on execution. +0002000&Set group id on execution. +0001000&Save swapped text even after use. +0000400&Read permission for owner. +0000200&Write permission for owner. +0000100&Execute and search permission for owner. +0000040&Read permission for group. +0000020&Write permission for group. +0000010&Execute and search permission for group. +0000004&Read permission for others. +0000002&Write permission for others. +0000001&Execute and search permission for others. +.TE +.KS +Notes: +.IP +The bits are the same as the mode bits returned by the +.I stat(2) +system call in the UNIX system. The file type is specified both in +the mode bits and in the file type. This is fixed in future +versions. +.IP +The "rdev" field in the attributes structure is an operating system +specific device specifier. It will be removed and generalized in +the next revision of the protocol. +.KE +.LP +.KS +.NH 3 +\&sattr +.IX "NFS data types" sattr "" \fIsattr\fP +.DS +struct sattr { + unsigned int mode; + unsigned int uid; + unsigned int gid; + unsigned int size; + timeval atime; + timeval mtime; +}; +.DE +.KE +The +.I sattr +structure contains the file attributes which can be set +from the client. The fields are the same as for +.I fattr +above. A "size" of zero means the file should be truncated. +A value of -1 indicates a field that should be ignored. +.LP +.KS +.NH 3 +\&filename +.IX "NFS data types" filename "" \fIfilename\fP +.DS +typedef string filename; +.DE +.KE +The type +.I filename +is used for passing file names or pathname components. +.LP +.KS +.NH 3 +\&path +.IX "NFS data types" path "" \fIpath\fP +.DS +typedef string path; +.DE +.KE +The type +.I path +is a pathname. The server considers it as a string +with no internal structure, but to the client it is the name of a +node in a filesystem tree. +.LP +.KS +.NH 3 +\&attrstat +.IX "NFS data types" attrstat "" \fIattrstat\fP +.DS +union attrstat switch (stat status) { + case NFS_OK: + fattr attributes; + default: + void; +}; +.DE +.KE +The +.I attrstat +structure is a common procedure result. It contains +a "status" and, if the call succeeded, it also contains the +attributes of the file on which the operation was done. +.LP +.KS +.NH 3 +\&diropargs +.IX "NFS data types" diropargs "" \fIdiropargs\fP +.DS +struct diropargs { + fhandle dir; + filename name; +}; +.DE +.KE +The +.I diropargs +structure is used in directory operations. The +"fhandle" "dir" is the directory in which to find the file "name". +A directory operation is one in which the directory is affected. +.LP +.KS +.NH 3 +\&diropres +.IX "NFS data types" diropres "" \fIdiropres\fP +.DS +union diropres switch (stat status) { + case NFS_OK: + struct { + fhandle file; + fattr attributes; + } diropok; + default: + void; +}; +.DE +.KE +The results of a directory operation are returned in a +.I diropres +structure. If the call succeeded, a new file handle "file" and the +"attributes" associated with that file are returned along with the +"status". +.NH 2 +\&Server Procedures +.IX "NFS server procedures" "" "" "" PAGE MAJOR +.LP +The protocol definition is given as a set of procedures with +arguments and results defined using the RPC language. A brief +description of the function of each procedure should provide enough +information to allow implementation. +.LP +All of the procedures in the NFS protocol are assumed to be +synchronous. When a procedure returns to the client, the client +can assume that the operation has completed and any data associated +with the request is now on stable storage. For example, a client +.I WRITE +request may cause the server to update data blocks, +filesystem information blocks (such as indirect blocks), and file +attribute information (size and modify times). When the +.I WRITE +returns to the client, it can assume that the write is safe, even +in case of a server crash, and it can discard the data written. +This is a very important part of the statelessness of the server. +If the server waited to flush data from remote requests, the client +would have to save those requests so that it could resend them in +case of a server crash. +.ie t .DS +.el .DS L + +.ft I +/* +* Remote file service routines +*/ +.ft CW +program NFS_PROGRAM { + version NFS_VERSION { + void NFSPROC_NULL(void) = 0; + attrstat NFSPROC_GETATTR(fhandle) = 1; + attrstat NFSPROC_SETATTR(sattrargs) = 2; + void NFSPROC_ROOT(void) = 3; + diropres NFSPROC_LOOKUP(diropargs) = 4; + readlinkres NFSPROC_READLINK(fhandle) = 5; + readres NFSPROC_READ(readargs) = 6; + void NFSPROC_WRITECACHE(void) = 7; + attrstat NFSPROC_WRITE(writeargs) = 8; + diropres NFSPROC_CREATE(createargs) = 9; + stat NFSPROC_REMOVE(diropargs) = 10; + stat NFSPROC_RENAME(renameargs) = 11; + stat NFSPROC_LINK(linkargs) = 12; + stat NFSPROC_SYMLINK(symlinkargs) = 13; + diropres NFSPROC_MKDIR(createargs) = 14; + stat NFSPROC_RMDIR(diropargs) = 15; + readdirres NFSPROC_READDIR(readdirargs) = 16; + statfsres NFSPROC_STATFS(fhandle) = 17; + } = 2; +} = 100003; +.DE +.KS +.NH 3 +\&Do Nothing +.IX "NFS server procedures" NFSPROC_NULL() "" \fINFSPROC_NULL()\fP +.DS +void +NFSPROC_NULL(void) = 0; +.DE +.KE +This procedure does no work. It is made available in all RPC +services to allow server response testing and timing. +.KS +.NH 3 +\&Get File Attributes +.IX "NFS server procedures" NFSPROC_GETATTR() "" \fINFSPROC_GETATTR()\fP +.DS +attrstat +NFSPROC_GETATTR (fhandle) = 1; +.DE +.KE +If the reply status is +.I NFS_OK , +then the reply attributes contains +the attributes for the file given by the input fhandle. +.KS +.NH 3 +\&Set File Attributes +.IX "NFS server procedures" NFSPROC_SETATTR() "" \fINFSPROC_SETATTR()\fP +.DS +struct sattrargs { + fhandle file; + sattr attributes; + }; + +attrstat +NFSPROC_SETATTR (sattrargs) = 2; +.DE +.KE +The "attributes" argument contains fields which are either -1 or +are the new value for the attributes of "file". If the reply +status is +.I NFS_OK , +then the reply attributes have the attributes of +the file after the "SETATTR" operation has completed. +.LP +Note: The use of -1 to indicate an unused field in "attributes" is +changed in the next version of the protocol. +.KS +.NH 3 +\&Get Filesystem Root +.IX "NFS server procedures" NFSPROC_ROOT "" \fINFSPROC_ROOT\fP +.DS +void +NFSPROC_ROOT(void) = 3; +.DE +.KE +Obsolete. This procedure is no longer used because finding the +root file handle of a filesystem requires moving pathnames between +client and server. To do this right we would have to define a +network standard representation of pathnames. Instead, the +function of looking up the root file handle is done by the +.I MNTPROC_MNT() +procedure. (See the +.I "Mount Protocol Definition" +later in this chapter for details). +.KS +.NH 3 +\&Look Up File Name +.IX "NFS server procedures" NFSPROC_LOOKUP() "" \fINFSPROC_LOOKUP()\fP +.DS +diropres +NFSPROC_LOOKUP(diropargs) = 4; +.DE +.KE +If the reply "status" is +.I NFS_OK , +then the reply "file" and reply +"attributes" are the file handle and attributes for the file "name" +in the directory given by "dir" in the argument. +.KS +.NH 3 +\&Read From Symbolic Link +.IX "NFS server procedures" NFSPROC_READLINK() "" \fINFSPROC_READLINK()\fP +.DS +union readlinkres switch (stat status) { + case NFS_OK: + path data; + default: + void; +}; + +readlinkres +NFSPROC_READLINK(fhandle) = 5; +.DE +.KE +If "status" has the value +.I NFS_OK , +then the reply "data" is the data in +the symbolic link given by the file referred to by the fhandle argument. +.LP +Note: since NFS always parses pathnames on the client, the +pathname in a symbolic link may mean something different (or be +meaningless) on a different client or on the server if a different +pathname syntax is used. +.KS +.NH 3 +\&Read From File +.IX "NFS server procedures" NFSPROC_READ "" \fINFSPROC_READ\fP +.DS +struct readargs { + fhandle file; + unsigned offset; + unsigned count; + unsigned totalcount; +}; + +union readres switch (stat status) { + case NFS_OK: + fattr attributes; + opaque data; + default: + void; +}; + +readres +NFSPROC_READ(readargs) = 6; +.DE +.KE +Returns up to "count" bytes of "data" from the file given by +"file", starting at "offset" bytes from the beginning of the file. +The first byte of the file is at offset zero. The file attributes +after the read takes place are returned in "attributes". +.LP +Note: The argument "totalcount" is unused, and is removed in the +next protocol revision. +.KS +.NH 3 +\&Write to Cache +.IX "NFS server procedures" NFSPROC_WRITECACHE() "" \fINFSPROC_WRITECACHE()\fP +.DS +void +NFSPROC_WRITECACHE(void) = 7; +.DE +.KE +To be used in the next protocol revision. +.KS +.NH 3 +\&Write to File +.IX "NFS server procedures" NFSPROC_WRITE() "" \fINFSPROC_WRITE()\fP +.DS +struct writeargs { + fhandle file; + unsigned beginoffset; + unsigned offset; + unsigned totalcount; + opaque data; +}; + +attrstat +NFSPROC_WRITE(writeargs) = 8; +.DE +.KE +Writes "data" beginning "offset" bytes from the beginning of +"file". The first byte of the file is at offset zero. If the +reply "status" is NFS_OK, then the reply "attributes" contains the +attributes of the file after the write has completed. The write +operation is atomic. Data from this call to +.I WRITE +will not be mixed with data from another client's calls. +.LP +Note: The arguments "beginoffset" and "totalcount" are ignored and +are removed in the next protocol revision. +.KS +.NH 3 +\&Create File +.IX "NFS server procedures" NFSPROC_CREATE() "" \fINFSPROC_CREATE()\fP +.DS +struct createargs { + diropargs where; + sattr attributes; +}; + +diropres +NFSPROC_CREATE(createargs) = 9; +.DE +.KE +The file "name" is created in the directory given by "dir". The +initial attributes of the new file are given by "attributes". A +reply "status" of NFS_OK indicates that the file was created, and +reply "file" and reply "attributes" are its file handle and +attributes. Any other reply "status" means that the operation +failed and no file was created. +.LP +Note: This routine should pass an exclusive create flag, meaning +"create the file only if it is not already there". +.KS +.NH 3 +\&Remove File +.IX "NFS server procedures" NFSPROC_REMOVE() "" \fINFSPROC_REMOVE()\fP +.DS +stat +NFSPROC_REMOVE(diropargs) = 10; +.DE +.KE +The file "name" is removed from the directory given by "dir". A +reply of NFS_OK means the directory entry was removed. +.LP +Note: possibly non-idempotent operation. +.KS +.NH 3 +\&Rename File +.IX "NFS server procedures" NFSPROC_RENAME() "" \fINFSPROC_RENAME()\fP +.DS +struct renameargs { + diropargs from; + diropargs to; +}; + +stat +NFSPROC_RENAME(renameargs) = 11; +.DE +.KE +The existing file "from.name" in the directory given by "from.dir" +is renamed to "to.name" in the directory given by "to.dir". If the +reply is +.I NFS_OK , +the file was renamed. The +RENAME +operation is +atomic on the server; it cannot be interrupted in the middle. +.LP +Note: possibly non-idempotent operation. +.KS +.NH 3 +\&Create Link to File +.IX "NFS server procedures" NFSPROC_LINK() "" \fINFSPROC_LINK()\fP +.DS +struct linkargs { + fhandle from; + diropargs to; +}; + +stat +NFSPROC_LINK(linkargs) = 12; +.DE +.KE +Creates the file "to.name" in the directory given by "to.dir", +which is a hard link to the existing file given by "from". If the +return value is +.I NFS_OK , +a link was created. Any other return value +indicates an error, and the link was not created. +.LP +A hard link should have the property that changes to either of the +linked files are reflected in both files. When a hard link is made +to a file, the attributes for the file should have a value for +"nlink" that is one greater than the value before the link. +.LP +Note: possibly non-idempotent operation. +.KS +.NH 3 +\&Create Symbolic Link +.IX "NFS server procedures" NFSPROC_SYMLINK() "" \fINFSPROC_SYMLINK()\fP +.DS +struct symlinkargs { + diropargs from; + path to; + sattr attributes; +}; + +stat +NFSPROC_SYMLINK(symlinkargs) = 13; +.DE +.KE +Creates the file "from.name" with ftype +.I NFLNK +in the directory +given by "from.dir". The new file contains the pathname "to" and +has initial attributes given by "attributes". If the return value +is +.I NFS_OK , +a link was created. Any other return value indicates an +error, and the link was not created. +.LP +A symbolic link is a pointer to another file. The name given in +"to" is not interpreted by the server, only stored in the newly +created file. When the client references a file that is a symbolic +link, the contents of the symbolic link are normally transparently +reinterpreted as a pathname to substitute. A +.I READLINK +operation returns the data to the client for interpretation. +.LP +Note: On UNIX servers the attributes are never used, since +symbolic links always have mode 0777. +.KS +.NH 3 +\&Create Directory +.IX "NFS server procedures" NFSPROC_MKDIR() "" \fINFSPROC_MKDIR()\fP +.DS +diropres +NFSPROC_MKDIR (createargs) = 14; +.DE +.KE +The new directory "where.name" is created in the directory given by +"where.dir". The initial attributes of the new directory are given +by "attributes". A reply "status" of NFS_OK indicates that the new +directory was created, and reply "file" and reply "attributes" are +its file handle and attributes. Any other reply "status" means +that the operation failed and no directory was created. +.LP +Note: possibly non-idempotent operation. +.KS +.NH 3 +\&Remove Directory +.IX "NFS server procedures" NFSPROC_RMDIR() "" \fINFSPROC_RMDIR()\fP +.DS +stat +NFSPROC_RMDIR(diropargs) = 15; +.DE +.KE +The existing empty directory "name" in the directory given by "dir" +is removed. If the reply is +.I NFS_OK , +the directory was removed. +.LP +Note: possibly non-idempotent operation. +.KS +.NH 3 +\&Read From Directory +.IX "NFS server procedures" NFSPROC_READDIR() "" \fINFSPROC_READDIR()\fP +.DS +struct readdirargs { + fhandle dir; + nfscookie cookie; + unsigned count; +}; + +struct entry { + unsigned fileid; + filename name; + nfscookie cookie; + entry *nextentry; +}; + +union readdirres switch (stat status) { + case NFS_OK: + struct { + entry *entries; + bool eof; + } readdirok; + default: + void; +}; + +readdirres +NFSPROC_READDIR (readdirargs) = 16; +.DE +.KE +Returns a variable number of directory entries, with a total size +of up to "count" bytes, from the directory given by "dir". If the +returned value of "status" is +.I NFS_OK , +then it is followed by a +variable number of "entry"s. Each "entry" contains a "fileid" +which consists of a unique number to identify the file within a +filesystem, the "name" of the file, and a "cookie" which is an +opaque pointer to the next entry in the directory. The cookie is +used in the next +.I READDIR +call to get more entries starting at a +given point in the directory. The special cookie zero (all bits +zero) can be used to get the entries starting at the beginning of +the directory. The "fileid" field should be the same number as the +"fileid" in the the attributes of the file. (See the +.I "Basic Data Types" +section.) +The "eof" flag has a value of +.I TRUE +if there are no more entries in the directory. +.KS +.NH 3 +\&Get Filesystem Attributes +.IX "NFS server procedures" NFSPROC_STATFS() "" \fINFSPROC_STATFS()\fP +.DS +union statfsres (stat status) { + case NFS_OK: + struct { + unsigned tsize; + unsigned bsize; + unsigned blocks; + unsigned bfree; + unsigned bavail; + } info; + default: + void; +}; + +statfsres +NFSPROC_STATFS(fhandle) = 17; +.DE +.KE +If the reply "status" is +.I NFS_OK , +then the reply "info" gives the +attributes for the filesystem that contains file referred to by the +input fhandle. The attribute fields contain the following values: +.IP tsize: +The optimum transfer size of the server in bytes. This is +the number of bytes the server would like to have in the +data part of READ and WRITE requests. +.IP bsize: +The block size in bytes of the filesystem. +.IP blocks: +The total number of "bsize" blocks on the filesystem. +.IP bfree: +The number of free "bsize" blocks on the filesystem. +.IP bavail: +The number of "bsize" blocks available to non-privileged users. +.LP +Note: This call does not work well if a filesystem has variable +size blocks. +.NH 1 +\&NFS Implementation Issues +.IX NFS implementation +.LP +The NFS protocol is designed to be operating system independent, but +since this version was designed in a UNIX environment, many +operations have semantics similar to the operations of the UNIX file +system. This section discusses some of the implementation-specific +semantic issues. +.NH 2 +\&Server/Client Relationship +.IX NFS "server/client relationship" +.LP +The NFS protocol is designed to allow servers to be as simple and +general as possible. Sometimes the simplicity of the server can be a +problem, if the client wants to implement complicated filesystem +semantics. +.LP +For example, some operating systems allow removal of open files. A +process can open a file and, while it is open, remove it from the +directory. The file can be read and written as long as the process +keeps it open, even though the file has no name in the filesystem. +It is impossible for a stateless server to implement these semantics. +The client can do some tricks such as renaming the file on remove, +and only removing it on close. We believe that the server provides +enough functionality to implement most file system semantics on the +client. +.LP +Every NFS client can also potentially be a server, and remote and +local mounted filesystems can be freely intermixed. This leads to +some interesting problems when a client travels down the directory +tree of a remote filesystem and reaches the mount point on the server +for another remote filesystem. Allowing the server to follow the +second remote mount would require loop detection, server lookup, and +user revalidation. Instead, we decided not to let clients cross a +server's mount point. When a client does a LOOKUP on a directory on +which the server has mounted a filesystem, the client sees the +underlying directory instead of the mounted directory. A client can +do remote mounts that match the server's mount points to maintain the +server's view. +.LP +.NH 2 +\&Pathname Interpretation +.IX NFS "pathname interpretation" +.LP +There are a few complications to the rule that pathnames are always +parsed on the client. For example, symbolic links could have +different interpretations on different clients. Another common +problem for non-UNIX implementations is the special interpretation of +the pathname ".." to mean the parent of a given directory. The next +revision of the protocol uses an explicit flag to indicate the parent +instead. +.NH 2 +\&Permission Issues +.IX NFS "permission issues" +.LP +The NFS protocol, strictly speaking, does not define the permission +checking used by servers. However, it is expected that a server +will do normal operating system permission checking using +.I AUTH_UNIX +style authentication as the basis of its protection mechanism. The +server gets the client's effective "uid", effective "gid", and groups +on each call and uses them to check permission. There are various +problems with this method that can been resolved in interesting ways. +.LP +Using "uid" and "gid" implies that the client and server share the +same "uid" list. Every server and client pair must have the same +mapping from user to "uid" and from group to "gid". Since every +client can also be a server, this tends to imply that the whole +network shares the same "uid/gid" space. +.I AUTH_DES +(and the next +revision of the NFS protocol) uses string names instead of numbers, +but there are still complex problems to be solved. +.LP +Another problem arises due to the usually stateful open operation. +Most operating systems check permission at open time, and then check +that the file is open on each read and write request. With stateless +servers, the server has no idea that the file is open and must do +permission checking on each read and write call. On a local +filesystem, a user can open a file and then change the permissions so +that no one is allowed to touch it, but will still be able to write +to the file because it is open. On a remote filesystem, by contrast, +the write would fail. To get around this problem, the server's +permission checking algorithm should allow the owner of a file to +access it regardless of the permission setting. +.LP +A similar problem has to do with paging in from a file over the +network. The operating system usually checks for execute permission +before opening a file for demand paging, and then reads blocks from +the open file. The file may not have read permission, but after it +is opened it doesn't matter. An NFS server can not tell the +difference between a normal file read and a demand page-in read. To +make this work, the server allows reading of files if the "uid" given +in the call has execute or read permission on the file. +.LP +In most operating systems, a particular user (on the user ID zero) +has access to all files no matter what permission and ownership they +have. This "super-user" permission may not be allowed on the server, +since anyone who can become super-user on their workstation could +gain access to all remote files. The UNIX server by default maps +user id 0 to -2 before doing its access checking. This works except +for NFS root filesystems, where super-user access cannot be avoided. +.NH 2 +\&Setting RPC Parameters +.IX NFS "setting RPC parameters" +.LP +Various file system parameters and options should be set at mount +time. The mount protocol is described in the appendix below. For +example, "Soft" mounts as well as "Hard" mounts are usually both +provided. Soft mounted file systems return errors when RPC +operations fail (after a given number of optional retransmissions), +while hard mounted file systems continue to retransmit forever. +Clients and servers may need to keep caches of recent operations to +help avoid problems with non-idempotent operations. +.NH 1 +\&Mount Protocol Definition +.IX "mount protocol" "" "" "" PAGE MAJOR +.sp 1 +.NH 2 +\&Introduction +.IX "mount protocol" introduction +.LP +The mount protocol is separate from, but related to, the NFS +protocol. It provides operating system specific services to get the +NFS off the ground -- looking up server path names, validating user +identity, and checking access permissions. Clients use the mount +protocol to get the first file handle, which allows them entry into a +remote filesystem. +.LP +The mount protocol is kept separate from the NFS protocol to make it +easy to plug in new access checking and validation methods without +changing the NFS server protocol. +.LP +Notice that the protocol definition implies stateful servers because +the server maintains a list of client's mount requests. The mount +list information is not critical for the correct functioning of +either the client or the server. It is intended for advisory use +only, for example, to warn possible clients when a server is going +down. +.LP +Version one of the mount protocol is used with version two of the NFS +protocol. The only connecting point is the +.I fhandle +structure, which is the same for both protocols. +.NH 2 +\&RPC Information +.IX "mount protocol" "RPC information" +.IP \fIAuthentication\fP +The mount service uses +.I AUTH_UNIX +and +.I AUTH_DES +style authentication only. +.IP "\fITransport Protocols\fP" +The mount service is currently supported on UDP/IP only. +.IP "\fIPort Number\fP" +Consult the server's portmapper, described in the chapter +.I "Remote Procedure Calls: Protocol Specification", +to find the port number on which the mount service is registered. +.NH 2 +\&Sizes of XDR Structures +.IX "mount protocol" "XDR structure sizes" +.LP +These are the sizes, given in decimal bytes, of various XDR +structures used in the protocol: +.DS +/* \fIThe maximum number of bytes in a pathname argument\fP */ +const MNTPATHLEN = 1024; + +/* \fIThe maximum number of bytes in a name argument\fP */ +const MNTNAMLEN = 255; + +/* \fIThe size in bytes of the opaque file handle\fP */ +const FHSIZE = 32; +.DE +.NH 2 +\&Basic Data Types +.IX "mount protocol" "basic data types" +.IX "mount data types" +.LP +This section presents the data types used by the mount protocol. +In many cases they are similar to the types used in NFS. +.KS +.NH 3 +\&fhandle +.IX "mount data types" fhandle "" \fIfhandle\fP +.DS +typedef opaque fhandle[FHSIZE]; +.DE +.KE +The type +.I fhandle +is the file handle that the server passes to the +client. All file operations are done using file handles to refer +to a file or directory. The file handle can contain whatever +information the server needs to distinguish an individual file. +.LP +This is the same as the "fhandle" XDR definition in version 2 of +the NFS protocol; see +.I "Basic Data Types" +in the definition of the NFS protocol, above. +.KS +.NH 3 +\&fhstatus +.IX "mount data types" fhstatus "" \fIfhstatus\fP +.DS +union fhstatus switch (unsigned status) { + case 0: + fhandle directory; + default: + void; +}; +.DE +.KE +The type +.I fhstatus +is a union. If a "status" of zero is returned, +the call completed successfully, and a file handle for the +"directory" follows. A non-zero status indicates some sort of +error. In this case the status is a UNIX error number. +.KS +.NH 3 +\&dirpath +.IX "mount data types" dirpath "" \fIdirpath\fP +.DS +typedef string dirpath; +.DE +.KE +The type +.I dirpath +is a server pathname of a directory. +.KS +.NH 3 +\&name +.IX "mount data types" name "" \fIname\fP +.DS +typedef string name; +.DE +.KE +The type +.I name +is an arbitrary string used for various names. +.NH 2 +\&Server Procedures +.IX "mount server procedures" +.LP +The following sections define the RPC procedures supplied by a +mount server. +.ie t .DS +.el .DS L +.ft I +/* +* Protocol description for the mount program +*/ +.ft CW + +program MOUNTPROG { +.ft I +/* +* Version 1 of the mount protocol used with +* version 2 of the NFS protocol. +*/ +.ft CW + version MOUNTVERS { + void MOUNTPROC_NULL(void) = 0; + fhstatus MOUNTPROC_MNT(dirpath) = 1; + mountlist MOUNTPROC_DUMP(void) = 2; + void MOUNTPROC_UMNT(dirpath) = 3; + void MOUNTPROC_UMNTALL(void) = 4; + exportlist MOUNTPROC_EXPORT(void) = 5; + } = 1; +} = 100005; +.DE +.KS +.NH 3 +\&Do Nothing +.IX "mount server procedures" MNTPROC_NULL() "" \fIMNTPROC_NULL()\fP +.DS +void +MNTPROC_NULL(void) = 0; +.DE +.KE +This procedure does no work. It is made available in all RPC +services to allow server response testing and timing. +.KS +.NH 3 +\&Add Mount Entry +.IX "mount server procedures" MNTPROC_MNT() "" \fIMNTPROC_MNT()\fP +.DS +fhstatus +MNTPROC_MNT(dirpath) = 1; +.DE +.KE +If the reply "status" is 0, then the reply "directory" contains the +file handle for the directory "dirname". This file handle may be +used in the NFS protocol. This procedure also adds a new entry to +the mount list for this client mounting "dirname". +.KS +.NH 3 +\&Return Mount Entries +.IX "mount server procedures" MNTPROC_DUMP() "" \fIMNTPROC_DUMP()\fP +.DS +struct *mountlist { + name hostname; + dirpath directory; + mountlist nextentry; +}; + +mountlist +MNTPROC_DUMP(void) = 2; +.DE +.KE +Returns the list of remote mounted filesystems. The "mountlist" +contains one entry for each "hostname" and "directory" pair. +.KS +.NH 3 +\&Remove Mount Entry +.IX "mount server procedures" MNTPROC_UMNT() "" \fIMNTPROC_UMNT()\fP +.DS +void +MNTPROC_UMNT(dirpath) = 3; +.DE +.KE +Removes the mount list entry for the input "dirpath". +.KS +.NH 3 +\&Remove All Mount Entries +.IX "mount server procedures" MNTPROC_UMNTALL() "" \fIMNTPROC_UMNTALL()\fP +.DS +void +MNTPROC_UMNTALL(void) = 4; +.DE +.KE +Removes all of the mount list entries for this client. +.KS +.NH 3 +\&Return Export List +.IX "mount server procedures" MNTPROC_EXPORT() "" \fIMNTPROC_EXPORT()\fP +.DS +struct *groups { + name grname; + groups grnext; +}; + +struct *exportlist { + dirpath filesys; + groups groups; + exportlist next; +}; + +exportlist +MNTPROC_EXPORT(void) = 5; +.DE +.KE +Returns a variable number of export list entries. Each entry +contains a filesystem name and a list of groups that are allowed to +import it. The filesystem name is in "filesys", and the group name +is in the list "groups". +.LP +Note: The exportlist should contain +more information about the status of the filesystem, such as a +read-only flag. diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/rpc.prog.ms b/c/src/exec/librpc/src/rpc/PSD.doc/rpc.prog.ms index e69de29bb2..3b02447fe8 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/rpc.prog.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/rpc.prog.ms @@ -0,0 +1,2684 @@ +.\" +.\" Must use -- tbl and pic -- with this one +.\" +.\" @(#)rpc.prog.ms 2.3 88/08/11 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.IX "Network Programming" "" "" "" PAGE MAJOR +.nr OF 0 +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'Remote Procedure Call Programming Guide''Page %' +.EH 'Page %''Remote Procedure Call Programming Guide' +.SH +\&Remote Procedure Call Programming Guide +.nr OF 1 +.IX "RPC Programming Guide" +.LP +This document assumes a working knowledge of network theory. It is +intended for programmers who wish to write network applications using +remote procedure calls (explained below), and who want to understand +the RPC mechanisms usually hidden by the +.I rpcgen(1) +protocol compiler. +.I rpcgen +is described in detail in the previous chapter, the +.I "\fBrpcgen\fP \fIProgramming Guide\fP". +.SH +Note: +.I +.IX rpcgen "" \fIrpcgen\fP +Before attempting to write a network application, or to convert an +existing non-network application to run over the network, you may want to +understand the material in this chapter. However, for most applications, +you can circumvent the need to cope with the details presented here by using +.I rpcgen . +The +.I "Generating XDR Routines" +section of that chapter contains the complete source for a working RPC +service\(ema remote directory listing service which uses +.I rpcgen +to generate XDR routines as well as client and server stubs. +.LP +.LP +What are remote procedure calls? Simply put, they are the high-level +communications paradigm used in the operating system. +RPC presumes the existence of +low-level networking mechanisms (such as TCP/IP and UDP/IP), and upon them +it implements a logical client to server communications system designed +specifically for the support of network applications. With RPC, the client +makes a procedure call to send a data packet to the server. When the +packet arrives, the server calls a dispatch routine, performs whatever +service is requested, sends back the reply, and the procedure call returns +to the client. +.NH 0 +\&Layers of RPC +.IX "layers of RPC" +.IX "RPC" "layers" +.LP +The RPC interface can be seen as being divided into three layers.\** +.FS +For a complete specification of the routines in the remote procedure +call Library, see the +.I rpc(3N) +manual page. +.FE +.LP +.I "The Highest Layer:" +.IX RPC "The Highest Layer" +The highest layer is totally transparent to the operating system, +machine and network upon which is is run. It's probably best to +think of this level as a way of +.I using +RPC, rather than as +a \fIpart of\fP RPC proper. Programmers who write RPC routines +should (almost) always make this layer available to others by way +of a simple C front end that entirely hides the networking. +.LP +To illustrate, at this level a program can simply make a call to +.I rnusers (), +a C routine which returns the number of users on a remote machine. +The user is not explicitly aware of using RPC \(em they simply +call a procedure, just as they would call +.I malloc() . +.LP +.I "The Middle Layer:" +.IX RPC "The Middle Layer" +The middle layer is really \*QRPC proper.\*U Here, the user doesn't +need to consider details about sockets, the UNIX system, or other low-level +implementation mechanisms. They simply make remote procedure calls +to routines on other machines. The selling point here is simplicity. +It's this layer that allows RPC to pass the \*Qhello world\*U test \(em +simple things should be simple. The middle-layer routines are used +for most applications. +.LP +RPC calls are made with the system routines +.I registerrpc() +.I callrpc() +and +.I svc_run (). +The first two of these are the most fundamental: +.I registerrpc() +obtains a unique system-wide procedure-identification number, and +.I callrpc() +actually executes a remote procedure call. At the middle level, a +call to +.I rnusers() +is implemented by way of these two routines. +.LP +The middle layer is unfortunately rarely used in serious programming +due to its inflexibility (simplicity). It does not allow timeout +specifications or the choice of transport. It allows no UNIX +process control or flexibility in case of errors. It doesn't support +multiple kinds of call authentication. The programmer rarely needs +all these kinds of control, but one or two of them is often necessary. +.LP +.I "The Lowest Layer:" +.IX RPC "The Lowest Layer" +The lowest layer does allow these details to be controlled by the +programmer, and for that reason it is often necessary. Programs +written at this level are also most efficient, but this is rarely a +real issue \(em since RPC clients and servers rarely generate +heavy network loads. +.LP +Although this document only discusses the interface to C, +remote procedure calls can be made from any language. +Even though this document discusses RPC +when it is used to communicate +between processes on different machines, +it works just as well for communication +between different processes on the same machine. +.br +.KS +.NH 2 +\&The RPC Paradigm +.IX RPC paradigm +.LP +Here is a diagram of the RPC paradigm: +.LP +\fBFigure 1-1\fI Network Communication with the Remote Reocedure Call\fR +.LP +.PS +L1: arrow down 1i "client " rjust "program " rjust +L2: line right 1.5i "\fIcallrpc\fP" "function" +move up 1.5i; line dotted down 6i; move up 4.5i +arrow right 1i +L3: arrow down 1i "invoke " rjust "service " rjust +L4: arrow right 1.5i "call" "service" +L5: arrow down 1i " service" ljust " executes" ljust +L6: arrow left 1.5i "\fIreturn\fP" "answer" +L7: arrow down 1i "request " rjust "completed " rjust +L8: line left 1i +arrow left 1.5i "\fIreturn\fP" "reply" +L9: arrow down 1i "program " rjust "continues " rjust +line dashed down from L2 to L9 +line dashed down from L4 to L7 +line dashed up 1i from L3 "service " rjust "daemon " rjust +arrow dashed down 1i from L8 +move right 1i from L3 +box invis "Machine B" +move left 1.2i from L2; move down +box invis "Machine A" +.PE +.KE +.KS +.NH 1 +\&Higher Layers of RPC +.NH 2 +\&Highest Layer +.IX "highest layer of RPC" +.IX RPC "highest layer" +.LP +Imagine you're writing a program that needs to know +how many users are logged into a remote machine. +You can do this by calling the RPC library routine +.I rnusers() +as illustrated below: +.ie t .DS +.el .DS L +.ft CW +#include + +main(argc, argv) + int argc; + char **argv; +{ + int num; + + if (argc != 2) { + fprintf(stderr, "usage: rnusers hostname\en"); + exit(1); + } + if ((num = rnusers(argv[1])) < 0) { + fprintf(stderr, "error: rnusers\en"); + exit(-1); + } + printf("%d users on %s\en", num, argv[1]); + exit(0); +} +.DE +.KE +RPC library routines such as +.I rnusers() +are in the RPC services library +.I librpcsvc.a +Thus, the program above should be compiled with +.DS +.ft CW +% cc \fIprogram.c -lrpcsvc\fP +.DE +.I rnusers (), +like the other RPC library routines, is documented in section 3R +of the +.I "System Interface Manual for the Sun Workstation" , +the same section which documents the standard Sun RPC services. +.IX "RPC Services" +See the +.I intro(3R) +manual page for an explanation of the documentation strategy +for these services and their RPC protocols. +.LP +Here are some of the RPC service library routines available to the +C programmer: +.LP +\fBTable 3-3\fI RPC Service Library Routines\RP +.TS +box tab (&) ; +cfI cfI +lfL l . +Routine&Description +_ +.sp.5 +rnusers&Return number of users on remote machine +rusers&Return information about users on remote machine +havedisk&Determine if remote machine has disk +rstats&Get performance data from remote kernel +rwall&Write to specified remote machines +yppasswd&Update user password in Yellow Pages +.TE +.LP +Other RPC services \(em for example +.I ether() +.I mount +.I rquota() +and +.I spray +\(em are not available to the C programmer as library routines. +They do, however, +have RPC program numbers so they can be invoked with +.I callrpc() +which will be discussed in the next section. Most of them also +have compilable +.I rpcgen(1) +protocol description files. (The +.I rpcgen +protocol compiler radically simplifies the process of developing +network applications. +See the \fBrpcgen\fI Programming Guide\fR +for detailed information about +.I rpcgen +and +.I rpcgen +protocol description files). +.KS +.NH 2 +\&Intermediate Layer +.IX "intermediate layer of RPC" +.IX "RPC" "intermediate layer" +.LP +The simplest interface, which explicitly makes RPC calls, uses the +functions +.I callrpc() +and +.I registerrpc() +Using this method, the number of remote users can be gotten as follows: +.ie t .DS +.el .DS L +#include +#include +#include +#include + +main(argc, argv) + int argc; + char **argv; +{ + unsigned long nusers; + int stat; + + if (argc != 2) { + fprintf(stderr, "usage: nusers hostname\en"); + exit(-1); + } + if (stat = callrpc(argv[1], + RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, + xdr_void, 0, xdr_u_long, &nusers) != 0) { + clnt_perrno(stat); + exit(1); + } + printf("%d users on %s\en", nusers, argv[1]); + exit(0); +} +.DE +.KE +Each RPC procedure is uniquely defined by a program number, +version number, and procedure number. The program number +specifies a group of related remote procedures, each of +which has a different procedure number. Each program also +has a version number, so when a minor change is made to a +remote service (adding a new procedure, for example), a new +program number doesn't have to be assigned. When you want +to call a procedure to find the number of remote users, you +look up the appropriate program, version and procedure numbers +in a manual, just as you look up the name of a memory allocator +when you want to allocate memory. +.LP +The simplest way of making remote procedure calls is with the the RPC +library routine +.I callrpc() +It has eight parameters. The first is the name of the remote server +machine. The next three parameters are the program, version, and procedure +numbers\(emtogether they identify the procedure to be called. +The fifth and sixth parameters are an XDR filter and an argument to +be encoded and passed to the remote procedure. +The final two parameters are a filter for decoding the results +returned by the remote procedure and a pointer to the place where +the procedure's results are to be stored. Multiple arguments and +results are handled by embedding them in structures. If +.I callrpc() +completes successfully, it returns zero; else it returns a nonzero +value. The return codes (of type +.IX "enum clnt_stat (in RPC programming)" "" "\fIenum clnt_stat\fP (in RPC programming)" +cast into an integer) are found in +.I . +.LP +Since data types may be represented differently on different machines, +.I callrpc() +needs both the type of the RPC argument, as well as +a pointer to the argument itself (and similarly for the result). For +.I RUSERSPROC_NUM , +the return value is an +.I "unsigned long" +so +.I callrpc() +has +.I xdr_u_long() +as its first return parameter, which says +that the result is of type +.I "unsigned long" +and +.I &nusers +as its second return parameter, +which is a pointer to where the long result will be placed. Since +.I RUSERSPROC_NUM +takes no argument, the argument parameter of +.I callrpc() +is +.I xdr_void (). +.LP +After trying several times to deliver a message, if +.I callrpc() +gets no answer, it returns with an error code. +The delivery mechanism is UDP, +which stands for User Datagram Protocol. +Methods for adjusting the number of retries +or for using a different protocol require you to use the lower +layer of the RPC library, discussed later in this document. +The remote server procedure +corresponding to the above might look like this: +.ie t .DS +.el .DS L +.ft CW +.ft CW +char * +nuser(indata) + char *indata; +{ + unsigned long nusers; + +.ft I + /* + * Code here to compute the number of users + * and place result in variable \fInusers\fP. + */ +.ft CW + return((char *)&nusers); +} +.DE +.LP +It takes one argument, which is a pointer to the input +of the remote procedure call (ignored in our example), +and it returns a pointer to the result. +In the current version of C, +character pointers are the generic pointers, +so both the input argument and the return value are cast to +.I "char *" . +.LP +Normally, a server registers all of the RPC calls it plans +to handle, and then goes into an infinite loop waiting to service requests. +In this example, there is only a single procedure +to register, so the main body of the server would look like this: +.ie t .DS +.el .DS L +.ft CW +#include +#include +#include +#include + +char *nuser(); + +main() +{ + registerrpc(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, + nuser, xdr_void, xdr_u_long); + svc_run(); /* \fINever returns\fP */ + fprintf(stderr, "Error: svc_run returned!\en"); + exit(1); +} +.DE +.LP +The +.I registerrpc() +routine registers a C procedure as corresponding to a +given RPC procedure number. The first three parameters, +.I RUSERPROG , +.I RUSERSVERS , +and +.I RUSERSPROC_NUM +are the program, version, and procedure numbers +of the remote procedure to be registered; +.I nuser() +is the name of the local procedure that implements the remote +procedure; and +.I xdr_void() +and +.I xdr_u_long() +are the XDR filters for the remote procedure's arguments and +results, respectively. (Multiple arguments or multiple results +are passed as structures). +.LP +Only the UDP transport mechanism can use +.I registerrpc() +thus, it is always safe in conjunction with calls generated by +.I callrpc() . +.SH +.IX "UDP 8K warning" +Warning: the UDP transport mechanism can only deal with +arguments and results less than 8K bytes in length. +.LP +.LP +After registering the local procedure, the server program's +main procedure calls +.I svc_run (), +the RPC library's remote procedure dispatcher. It is this +function that calls the remote procedures in response to RPC +call messages. Note that the dispatcher takes care of decoding +remote procedure arguments and encoding results, using the XDR +filters specified when the remote procedure was registered. +.NH 2 +\&Assigning Program Numbers +.IX "program number assignment" +.IX "assigning program numbers" +.LP +Program numbers are assigned in groups of +.I 0x20000000 +according to the following chart: +.DS +.ft CW + 0x0 - 0x1fffffff \fRDefined by Sun\fP +0x20000000 - 0x3fffffff \fRDefined by user\fP +0x40000000 - 0x5fffffff \fRTransient\fP +0x60000000 - 0x7fffffff \fRReserved\fP +0x80000000 - 0x9fffffff \fRReserved\fP +0xa0000000 - 0xbfffffff \fRReserved\fP +0xc0000000 - 0xdfffffff \fRReserved\fP +0xe0000000 - 0xffffffff \fRReserved\fP +.ft R +.DE +Sun Microsystems administers the first group of numbers, which +should be identical for all Sun customers. If a customer +develops an application that might be of general interest, that +application should be given an assigned number in the first +range. The second group of numbers is reserved for specific +customer applications. This range is intended primarily for +debugging new programs. The third group is reserved for +applications that generate program numbers dynamically. The +final groups are reserved for future use, and should not be +used. +.LP +To register a protocol specification, send a request by network +mail to +.I rpc@sun +or write to: +.DS +RPC Administrator +Sun Microsystems +2550 Garcia Ave. +Mountain View, CA 94043 +.DE +Please include a compilable +.I rpcgen +\*Q.x\*U file describing your protocol. +You will be given a unique program number in return. +.IX RPC administration +.IX administration "of RPC" +.LP +The RPC program numbers and protocol specifications +of standard Sun RPC services can be +found in the include files in +.I "/usr/include/rpcsvc" . +These services, however, constitute only a small subset +of those which have been registered. The complete list of +registered programs, as of the time when this manual was +printed, is: +.LP +\fBTable 3-2\fI RPC Registered Programs\fR +.TS H +box tab (&) ; +lfBI lfBI lfBI +lfL lfL lfI . +RPC Number&Program&Description +_ +.TH +.sp.5 +100000&PMAPPROG&portmapper +100001&RSTATPROG&remote stats +100002&RUSERSPROG&remote users +100003&NFSPROG&nfs +100004&YPPROG&Yellow Pages +100005&MOUNTPROG&mount demon +100006&DBXPROG&remote dbx +100007&YPBINDPROG&yp binder +100008&WALLPROG&shutdown msg +100009&YPPASSWDPROG&yppasswd server +100010ÐERSTATPROGðer stats +100011&RQUOTAPROG&disk quotas +100012&SPRAYPROG&spray packets +100013&IBM3270PROG&3270 mapper +100014&IBMRJEPROG&RJE mapper +100015&SELNSVCPROG&selection service +100016&RDATABASEPROG&remote database access +100017&REXECPROG&remote execution +100018&ALICEPROG&Alice Office Automation +100019&SCHEDPROG&scheduling service +100020&LOCKPROG&local lock manager +100021&NETLOCKPROG&network lock manager +100022&X25PROG&x.25 inr protocol +100023&STATMON1PROG&status monitor 1 +100024&STATMON2PROG&status monitor 2 +100025&SELNLIBPROG&selection library +100026&BOOTPARAMPROG&boot parameters service +100027&MAZEPROG&mazewars game +100028&YPUPDATEPROG&yp update +100029&KEYSERVEPROG&key server +100030&SECURECMDPROG&secure login +100031&NETFWDIPROG&nfs net forwarder init +100032&NETFWDTPROG&nfs net forwarder trans +100033&SUNLINKMAP_PROG&sunlink MAP +100034&NETMONPROG&network monitor +100035&DBASEPROG&lightweight database +100036&PWDAUTHPROG&password authorization +100037&TFSPROG&translucent file svc +100038&NSEPROG&nse server +100039&NSE_ACTIVATE_PROG&nse activate daemon +.sp .2i +150001&PCNFSDPROG&pc passwd authorization +.sp .2i +200000&PYRAMIDLOCKINGPROG&Pyramid-locking +200001&PYRAMIDSYS5&Pyramid-sys5 +200002&CADDS_IMAGE&CV cadds_image +.sp .2i +300001&ADT_RFLOCKPROG&ADT file locking +.TE +.NH 2 +\&Passing Arbitrary Data Types +.IX "arbitrary data types" +.LP +In the previous example, the RPC call passes a single +.I "unsigned long" +RPC can handle arbitrary data structures, regardless of +different machines' byte orders or structure layout conventions, +by always converting them to a network standard called +.I "External Data Representation" +(XDR) before +sending them over the wire. +The process of converting from a particular machine representation +to XDR format is called +.I serializing , +and the reverse process is called +.I deserializing . +The type field parameters of +.I callrpc() +and +.I registerrpc() +can be a built-in procedure like +.I xdr_u_long() +in the previous example, or a user supplied one. +XDR has these built-in type routines: +.IX RPC "built-in routines" +.DS +.ft CW +xdr_int() xdr_u_int() xdr_enum() +xdr_long() xdr_u_long() xdr_bool() +xdr_short() xdr_u_short() xdr_wrapstring() +xdr_char() xdr_u_char() +.DE +Note that the routine +.I xdr_string() +exists, but cannot be used with +.I callrpc() +and +.I registerrpc (), +which only pass two parameters to their XDR routines. +.I xdr_wrapstring() +has only two parameters, and is thus OK. It calls +.I xdr_string (). +.LP +As an example of a user-defined type routine, +if you wanted to send the structure +.DS +.ft CW +struct simple { + int a; + short b; +} simple; +.DE +then you would call +.I callrpc() +as +.DS +.ft CW +callrpc(hostname, PROGNUM, VERSNUM, PROCNUM, + xdr_simple, &simple ...); +.DE +where +.I xdr_simple() +is written as: +.ie t .DS +.el .DS L +.ft CW +#include + +xdr_simple(xdrsp, simplep) + XDR *xdrsp; + struct simple *simplep; +{ + if (!xdr_int(xdrsp, &simplep->a)) + return (0); + if (!xdr_short(xdrsp, &simplep->b)) + return (0); + return (1); +} +.DE +.LP +An XDR routine returns nonzero (true in the sense of C) if it +completes successfully, and zero otherwise. +A complete description of XDR is in the +.I "XDR Protocol Specification" +section of this manual, only few implementation examples are +given here. +.LP +In addition to the built-in primitives, +there are also the prefabricated building blocks: +.DS +.ft CW +xdr_array() xdr_bytes() xdr_reference() +xdr_vector() xdr_union() xdr_pointer() +xdr_string() xdr_opaque() +.DE +To send a variable array of integers, +you might package them up as a structure like this +.DS +.ft CW +struct varintarr { + int *data; + int arrlnth; +} arr; +.DE +and make an RPC call such as +.DS +.ft CW +callrpc(hostname, PROGNUM, VERSNUM, PROCNUM, + xdr_varintarr, &arr...); +.DE +with +.I xdr_varintarr() +defined as: +.ie t .DS +.el .DS L +.ft CW +xdr_varintarr(xdrsp, arrp) + XDR *xdrsp; + struct varintarr *arrp; +{ + return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth, + MAXLEN, sizeof(int), xdr_int)); +} +.DE +This routine takes as parameters the XDR handle, +a pointer to the array, a pointer to the size of the array, +the maximum allowable array size, +the size of each array element, +and an XDR routine for handling each array element. +.KS +.LP +If the size of the array is known in advance, one can use +.I xdr_vector (), +which serializes fixed-length arrays. +.ie t .DS +.el .DS L +.ft CW +int intarr[SIZE]; + +xdr_intarr(xdrsp, intarr) + XDR *xdrsp; + int intarr[]; +{ + int i; + + return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int), + xdr_int)); +} +.DE +.KE +.LP +XDR always converts quantities to 4-byte multiples when serializing. +Thus, if either of the examples above involved characters +instead of integers, each character would occupy 32 bits. +That is the reason for the XDR routine +.I xdr_bytes() +which is like +.I xdr_array() +except that it packs characters; +.I xdr_bytes() +has four parameters, similar to the first four parameters of +.I xdr_array (). +For null-terminated strings, there is also the +.I xdr_string() +routine, which is the same as +.I xdr_bytes() +without the length parameter. +On serializing it gets the string length from +.I strlen (), +and on deserializing it creates a null-terminated string. +.LP +Here is a final example that calls the previously written +.I xdr_simple() +as well as the built-in functions +.I xdr_string() +and +.I xdr_reference (), +which chases pointers: +.ie t .DS +.el .DS L +.ft CW +struct finalexample { + char *string; + struct simple *simplep; +} finalexample; + +xdr_finalexample(xdrsp, finalp) + XDR *xdrsp; + struct finalexample *finalp; +{ + + if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN)) + return (0); + if (!xdr_reference(xdrsp, &finalp->simplep, + sizeof(struct simple), xdr_simple); + return (0); + return (1); +} +.DE +Note that we could as easily call +.I xdr_simple() +here instead of +.I xdr_reference (). +.NH 1 +\&Lowest Layer of RPC +.IX "lowest layer of RPC" +.IX "RPC" "lowest layer" +.LP +In the examples given so far, +RPC takes care of many details automatically for you. +In this section, we'll show you how you can change the defaults +by using lower layers of the RPC library. +It is assumed that you are familiar with sockets +and the system calls for dealing with them. +.LP +There are several occasions when you may need to use lower layers of +RPC. First, you may need to use TCP, since the higher layer uses UDP, +which restricts RPC calls to 8K bytes of data. Using TCP permits calls +to send long streams of data. +For an example, see the +.I TCP +section below. Second, you may want to allocate and free memory +while serializing or deserializing with XDR routines. +There is no call at the higher level to let +you free memory explicitly. +For more explanation, see the +.I "Memory Allocation with XDR" +section below. +Third, you may need to perform authentication +on either the client or server side, by supplying +credentials or verifying them. +See the explanation in the +.I Authentication +section below. +.NH 2 +\&More on the Server Side +.IX RPC "server side" +.LP +The server for the +.I nusers() +program shown below does the same thing as the one using +.I registerrpc() +above, but is written using a lower layer of the RPC package: +.ie t .DS +.el .DS L +.ft CW +#include +#include +#include +#include + +main() +{ + SVCXPRT *transp; + int nuser(); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL){ + fprintf(stderr, "can't create an RPC server\en"); + exit(1); + } + pmap_unset(RUSERSPROG, RUSERSVERS); + if (!svc_register(transp, RUSERSPROG, RUSERSVERS, + nuser, IPPROTO_UDP)) { + fprintf(stderr, "can't register RUSER service\en"); + exit(1); + } + svc_run(); /* \fINever returns\fP */ + fprintf(stderr, "should never reach this point\en"); +} + +nuser(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + unsigned long nusers; + + switch (rqstp->rq_proc) { + case NULLPROC: + if (!svc_sendreply(transp, xdr_void, 0)) + fprintf(stderr, "can't reply to RPC call\en"); + return; + case RUSERSPROC_NUM: +.ft I + /* + * Code here to compute the number of users + * and assign it to the variable \fInusers\fP + */ +.ft CW + if (!svc_sendreply(transp, xdr_u_long, &nusers)) + fprintf(stderr, "can't reply to RPC call\en"); + return; + default: + svcerr_noproc(transp); + return; + } +} +.DE +.LP +First, the server gets a transport handle, which is used +for receiving and replying to RPC messages. +.I registerrpc() +uses +.I svcudp_create() +to get a UDP handle. +If you require a more reliable protocol, call +.I svctcp_create() +instead. +If the argument to +.I svcudp_create() +is +.I RPC_ANYSOCK +the RPC library creates a socket +on which to receive and reply to RPC calls. Otherwise, +.I svcudp_create() +expects its argument to be a valid socket number. +If you specify your own socket, it can be bound or unbound. +If it is bound to a port by the user, the port numbers of +.I svcudp_create() +and +.I clnttcp_create() +(the low-level client routine) must match. +.LP +If the user specifies the +.I RPC_ANYSOCK +argument, the RPC library routines will open sockets. +Otherwise they will expect the user to do so. The routines +.I svcudp_create() +and +.I clntudp_create() +will cause the RPC library routines to +.I bind() +their socket if it is not bound already. +.LP +A service may choose to register its port number with the +local portmapper service. This is done is done by specifying +a non-zero protocol number in +.I svc_register (). +Incidently, a client can discover the server's port number by +consulting the portmapper on their server's machine. This can +be done automatically by specifying a zero port number in +.I clntudp_create() +or +.I clnttcp_create (). +.LP +After creating an +.I SVCXPRT , +the next step is to call +.I pmap_unset() +so that if the +.I nusers() +server crashed earlier, +any previous trace of it is erased before restarting. +More precisely, +.I pmap_unset() +erases the entry for +.I RUSERSPROG +from the port mapper's tables. +.LP +Finally, we associate the program number for +.I nusers() +with the procedure +.I nuser (). +The final argument to +.I svc_register() +is normally the protocol being used, +which, in this case, is +.I IPPROTO_UDP +Notice that unlike +.I registerrpc (), +there are no XDR routines involved +in the registration process. +Also, registration is done on the program, +rather than procedure, level. +.LP +The user routine +.I nuser() +must call and dispatch the appropriate XDR routines +based on the procedure number. +Note that +two things are handled by +.I nuser() +that +.I registerrpc() +handles automatically. +The first is that procedure +.I NULLPROC +(currently zero) returns with no results. +This can be used as a simple test +for detecting if a remote program is running. +Second, there is a check for invalid procedure numbers. +If one is detected, +.I svcerr_noproc() +is called to handle the error. +.KS +.LP +The user service routine serializes the results and returns +them to the RPC caller via +.I svc_sendreply() +Its first parameter is the +.I SVCXPRT +handle, the second is the XDR routine, +and the third is a pointer to the data to be returned. +Not illustrated above is how a server +handles an RPC program that receives data. +As an example, we can add a procedure +.I RUSERSPROC_BOOL +which has an argument +.I nusers (), +and returns +.I TRUE +or +.I FALSE +depending on whether there are nusers logged on. +It would look like this: +.ie t .DS +.el .DS L +.ft CW +case RUSERSPROC_BOOL: { + int bool; + unsigned nuserquery; + + if (!svc_getargs(transp, xdr_u_int, &nuserquery) { + svcerr_decode(transp); + return; + } +.ft I + /* + * Code to set \fInusers\fP = number of users + */ +.ft CW + if (nuserquery == nusers) + bool = TRUE; + else + bool = FALSE; + if (!svc_sendreply(transp, xdr_bool, &bool)) { + fprintf(stderr, "can't reply to RPC call\en"); + return (1); + } + return; +} +.DE +.KE +.LP +The relevant routine is +.I svc_getargs() +which takes an +.I SVCXPRT +handle, the XDR routine, +and a pointer to where the input is to be placed as arguments. +.NH 2 +\&Memory Allocation with XDR +.IX "memory allocation with XDR" +.IX XDR "memory allocation" +.LP +XDR routines not only do input and output, +they also do memory allocation. +This is why the second parameter of +.I xdr_array() +is a pointer to an array, rather than the array itself. +If it is +.I NULL , +then +.I xdr_array() +allocates space for the array and returns a pointer to it, +putting the size of the array in the third argument. +As an example, consider the following XDR routine +.I xdr_chararr1() +which deals with a fixed array of bytes with length +.I SIZE . +.ie t .DS +.el .DS L +.ft CW +xdr_chararr1(xdrsp, chararr) + XDR *xdrsp; + char chararr[]; +{ + char *p; + int len; + + p = chararr; + len = SIZE; + return (xdr_bytes(xdrsp, &p, &len, SIZE)); +} +.DE +If space has already been allocated in +.I chararr , +it can be called from a server like this: +.ie t .DS +.el .DS L +.ft CW +char chararr[SIZE]; + +svc_getargs(transp, xdr_chararr1, chararr); +.DE +If you want XDR to do the allocation, +you would have to rewrite this routine in the following way: +.ie t .DS +.el .DS L +.ft CW +xdr_chararr2(xdrsp, chararrp) + XDR *xdrsp; + char **chararrp; +{ + int len; + + len = SIZE; + return (xdr_bytes(xdrsp, charrarrp, &len, SIZE)); +} +.DE +Then the RPC call might look like this: +.ie t .DS +.el .DS L +.ft CW +char *arrptr; + +arrptr = NULL; +svc_getargs(transp, xdr_chararr2, &arrptr); +.ft I +/* + * Use the result here + */ +.ft CW +svc_freeargs(transp, xdr_chararr2, &arrptr); +.DE +Note that, after being used, the character array can be freed with +.I svc_freeargs() +.I svc_freeargs() +will not attempt to free any memory if the variable indicating it +is NULL. For example, in the the routine +.I xdr_finalexample (), +given earlier, if +.I finalp->string +was NULL, then it would not be freed. The same is true for +.I finalp->simplep . +.LP +To summarize, each XDR routine is responsible +for serializing, deserializing, and freeing memory. +When an XDR routine is called from +.I callrpc() +the serializing part is used. +When called from +.I svc_getargs() +the deserializer is used. +And when called from +.I svc_freeargs() +the memory deallocator is used. When building simple examples like those +in this section, a user doesn't have to worry +about the three modes. +See the +.I "External Data Representation: Sun Technical Notes" +for examples of more sophisticated XDR routines that determine +which of the three modes they are in and adjust their behavior accordingly. +.KS +.NH 2 +\&The Calling Side +.IX RPC "calling side" +.LP +When you use +.I callrpc() +you have no control over the RPC delivery +mechanism or the socket used to transport the data. +To illustrate the layer of RPC that lets you adjust these +parameters, consider the following code to call the +.I nusers +service: +.ie t .DS +.el .DS L +.ft CW +.vs 11 +#include +#include +#include +#include +#include +#include +#include + +main(argc, argv) + int argc; + char **argv; +{ + struct hostent *hp; + struct timeval pertry_timeout, total_timeout; + struct sockaddr_in server_addr; + int sock = RPC_ANYSOCK; + register CLIENT *client; + enum clnt_stat clnt_stat; + unsigned long nusers; + + if (argc != 2) { + fprintf(stderr, "usage: nusers hostname\en"); + exit(-1); + } + if ((hp = gethostbyname(argv[1])) == NULL) { + fprintf(stderr, "can't get addr for %s\en",argv[1]); + exit(-1); + } + pertry_timeout.tv_sec = 3; + pertry_timeout.tv_usec = 0; + bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, + hp->h_length); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + if ((client = clntudp_create(&server_addr, RUSERSPROG, + RUSERSVERS, pertry_timeout, &sock)) == NULL) { + clnt_pcreateerror("clntudp_create"); + exit(-1); + } + total_timeout.tv_sec = 20; + total_timeout.tv_usec = 0; + clnt_stat = clnt_call(client, RUSERSPROC_NUM, xdr_void, + 0, xdr_u_long, &nusers, total_timeout); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(client, "rpc"); + exit(-1); + } + clnt_destroy(client); + close(sock); + exit(0); +} +.vs +.DE +.KE +The low-level version of +.I callrpc() +is +.I clnt_call() +which takes a +.I CLIENT +pointer rather than a host name. The parameters to +.I clnt_call() +are a +.I CLIENT +pointer, the procedure number, +the XDR routine for serializing the argument, +a pointer to the argument, +the XDR routine for deserializing the return value, +a pointer to where the return value will be placed, +and the time in seconds to wait for a reply. +.LP +The +.I CLIENT +pointer is encoded with the transport mechanism. +.I callrpc() +uses UDP, thus it calls +.I clntudp_create() +to get a +.I CLIENT +pointer. To get TCP (Transmission Control Protocol), you would use +.I clnttcp_create() . +.LP +The parameters to +.I clntudp_create() +are the server address, the program number, the version number, +a timeout value (between tries), and a pointer to a socket. +The final argument to +.I clnt_call() +is the total time to wait for a response. +Thus, the number of tries is the +.I clnt_call() +timeout divided by the +.I clntudp_create() +timeout. +.LP +Note that the +.I clnt_destroy() +call +always deallocates the space associated with the +.I CLIENT +handle. It closes the socket associated with the +.I CLIENT +handle, however, only if the RPC library opened it. It the +socket was opened by the user, it stays open. This makes it +possible, in cases where there are multiple client handles +using the same socket, to destroy one handle without closing +the socket that other handles are using. +.LP +To make a stream connection, the call to +.I clntudp_create() +is replaced with a call to +.I clnttcp_create() . +.DS +.ft CW +clnttcp_create(&server_addr, prognum, versnum, &sock, + inputsize, outputsize); +.DE +There is no timeout argument; instead, the receive and send buffer +sizes must be specified. When the +.I clnttcp_create() +call is made, a TCP connection is established. +All RPC calls using that +.I CLIENT +handle would use this connection. +The server side of an RPC call using TCP has +.I svcudp_create() +replaced by +.I svctcp_create() . +.DS +.ft CW +transp = svctcp_create(RPC_ANYSOCK, 0, 0); +.DE +The last two arguments to +.I svctcp_create() +are send and receive sizes respectively. If `0' is specified for +either of these, the system chooses a reasonable default. +.KS +.NH 1 +\&Other RPC Features +.IX "RPC" "miscellaneous features" +.IX "miscellaneous RPC features" +.LP +This section discusses some other aspects of RPC +that are occasionally useful. +.NH 2 +\&Select on the Server Side +.IX RPC select() RPC \fIselect()\fP +.IX select() "" \fIselect()\fP "on the server side" +.LP +Suppose a process is processing RPC requests +while performing some other activity. +If the other activity involves periodically updating a data structure, +the process can set an alarm signal before calling +.I svc_run() +But if the other activity +involves waiting on a a file descriptor, the +.I svc_run() +call won't work. +The code for +.I svc_run() +is as follows: +.ie t .DS +.el .DS L +.ft CW +.vs 11 +void +svc_run() +{ + fd_set readfds; + int dtbsz = getdtablesize(); + + for (;;) { + readfds = svc_fds; + switch (select(dtbsz, &readfds, NULL,NULL,NULL)) { + + case -1: + if (errno == EINTR) + continue; + perror("select"); + return; + case 0: + break; + default: + svc_getreqset(&readfds); + } + } +} +.vs +.DE +.KE +.LP +You can bypass +.I svc_run() +and call +.I svc_getreqset() +yourself. +All you need to know are the file descriptors +of the socket(s) associated with the programs you are waiting on. +Thus you can have your own +.I select() +.IX select() "" \fIselect()\fP +that waits on both the RPC socket, +and your own descriptors. Note that +.I svc_fds() +is a bit mask of all the file descriptors that RPC is using for +services. It can change everytime that +.I any +RPC library routine is called, because descriptors are constantly +being opened and closed, for example for TCP connections. +.NH 2 +\&Broadcast RPC +.IX "broadcast RPC" +.IX RPC "broadcast" +.LP +The +.I portmapper +is a daemon that converts RPC program numbers +into DARPA protocol port numbers; see the +.I portmap +man page. You can't do broadcast RPC without the portmapper. +Here are the main differences between +broadcast RPC and normal RPC calls: +.IP 1. +Normal RPC expects one answer, whereas +broadcast RPC expects many answers +(one or more answer from each responding machine). +.IP 2. +Broadcast RPC can only be supported by packet-oriented (connectionless) +transport protocols like UPD/IP. +.IP 3. +The implementation of broadcast RPC +treats all unsuccessful responses as garbage by filtering them out. +Thus, if there is a version mismatch between the +broadcaster and a remote service, +the user of broadcast RPC never knows. +.IP 4. +All broadcast messages are sent to the portmap port. +Thus, only services that register themselves with their portmapper +are accessible via the broadcast RPC mechanism. +.IP 5. +Broadcast requests are limited in size to the MTU (Maximum Transfer +Unit) of the local network. For Ethernet, the MTU is 1500 bytes. +.KS +.NH 3 +\&Broadcast RPC Synopsis +.IX "broadcast RPC" synopsis +.IX "RPC" "broadcast synopsis" +.ie t .DS +.el .DS L +.ft CW +#include + . . . +enum clnt_stat clnt_stat; + . . . +clnt_stat = clnt_broadcast(prognum, versnum, procnum, + inproc, in, outproc, out, eachresult) + u_long prognum; /* \fIprogram number\fP */ + u_long versnum; /* \fIversion number\fP */ + u_long procnum; /* \fIprocedure number\fP */ + xdrproc_t inproc; /* \fIxdr routine for args\fP */ + caddr_t in; /* \fIpointer to args\fP */ + xdrproc_t outproc; /* \fIxdr routine for results\fP */ + caddr_t out; /* \fIpointer to results\fP */ + bool_t (*eachresult)();/* \fIcall with each result gotten\fP */ +.DE +.KE +The procedure +.I eachresult() +is called each time a valid result is obtained. +It returns a boolean that indicates +whether or not the user wants more responses. +.ie t .DS +.el .DS L +.ft CW +bool_t done; + . . . +done = eachresult(resultsp, raddr) + caddr_t resultsp; + struct sockaddr_in *raddr; /* \fIAddr of responding machine\fP */ +.DE +If +.I done +is +.I TRUE , +then broadcasting stops and +.I clnt_broadcast() +returns successfully. +Otherwise, the routine waits for another response. +The request is rebroadcast +after a few seconds of waiting. +If no responses come back, +the routine returns with +.I RPC_TIMEDOUT . +.NH 2 +\&Batching +.IX "batching" +.IX RPC "batching" +.LP +The RPC architecture is designed so that clients send a call message, +and wait for servers to reply that the call succeeded. +This implies that clients do not compute +while servers are processing a call. +This is inefficient if the client does not want or need +an acknowledgement for every message sent. +It is possible for clients to continue computing +while waiting for a response, +using RPC batch facilities. +.LP +RPC messages can be placed in a \*Qpipeline\*U of calls +to a desired server; this is called batching. +Batching assumes that: +1) each RPC call in the pipeline requires no response from the server, +and the server does not send a response message; and +2) the pipeline of calls is transported on a reliable +byte stream transport such as TCP/IP. +Since the server does not respond to every call, +the client can generate new calls in parallel +with the server executing previous calls. +Furthermore, the TCP/IP implementation can buffer up +many call messages, and send them to the server in one +.I write() +system call. This overlapped execution +greatly decreases the interprocess communication overhead of +the client and server processes, +and the total elapsed time of a series of calls. +.LP +Since the batched calls are buffered, +the client should eventually do a nonbatched call +in order to flush the pipeline. +.LP +A contrived example of batching follows. +Assume a string rendering service (like a window system) +has two similar calls: one renders a string and returns void results, +while the other renders a string and remains silent. +The service (using the TCP/IP transport) may look like: +.ie t .DS +.el .DS L +.ft CW +#include +#include +#include + +void windowdispatch(); + +main() +{ + SVCXPRT *transp; + + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (transp == NULL){ + fprintf(stderr, "can't create an RPC server\en"); + exit(1); + } + pmap_unset(WINDOWPROG, WINDOWVERS); + if (!svc_register(transp, WINDOWPROG, WINDOWVERS, + windowdispatch, IPPROTO_TCP)) { + fprintf(stderr, "can't register WINDOW service\en"); + exit(1); + } + svc_run(); /* \fINever returns\fP */ + fprintf(stderr, "should never reach this point\en"); +} + +void +windowdispatch(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + char *s = NULL; + + switch (rqstp->rq_proc) { + case NULLPROC: + if (!svc_sendreply(transp, xdr_void, 0)) + fprintf(stderr, "can't reply to RPC call\en"); + return; + case RENDERSTRING: + if (!svc_getargs(transp, xdr_wrapstring, &s)) { + fprintf(stderr, "can't decode arguments\en"); +.ft I + /* + * Tell caller he screwed up + */ +.ft CW + svcerr_decode(transp); + break; + } +.ft I + /* + * Code here to render the string \fIs\fP + */ +.ft CW + if (!svc_sendreply(transp, xdr_void, NULL)) + fprintf(stderr, "can't reply to RPC call\en"); + break; + case RENDERSTRING_BATCHED: + if (!svc_getargs(transp, xdr_wrapstring, &s)) { + fprintf(stderr, "can't decode arguments\en"); +.ft I + /* + * We are silent in the face of protocol errors + */ +.ft CW + break; + } +.ft I + /* + * Code here to render string s, but send no reply! + */ +.ft CW + break; + default: + svcerr_noproc(transp); + return; + } +.ft I + /* + * Now free string allocated while decoding arguments + */ +.ft CW + svc_freeargs(transp, xdr_wrapstring, &s); +} +.DE +Of course the service could have one procedure +that takes the string and a boolean +to indicate whether or not the procedure should respond. +.LP +In order for a client to take advantage of batching, +the client must perform RPC calls on a TCP-based transport +and the actual calls must have the following attributes: +1) the result's XDR routine must be zero +.I NULL ), +and 2) the RPC call's timeout must be zero. +.KS +.LP +Here is an example of a client that uses batching to render a +bunch of strings; the batching is flushed when the client gets +a null string (EOF): +.ie t .DS +.el .DS L +.ft CW +.vs 11 +#include +#include +#include +#include +#include +#include + +main(argc, argv) + int argc; + char **argv; +{ + struct hostent *hp; + struct timeval pertry_timeout, total_timeout; + struct sockaddr_in server_addr; + int sock = RPC_ANYSOCK; + register CLIENT *client; + enum clnt_stat clnt_stat; + char buf[1000], *s = buf; + + if ((client = clnttcp_create(&server_addr, + WINDOWPROG, WINDOWVERS, &sock, 0, 0)) == NULL) { + perror("clnttcp_create"); + exit(-1); + } + total_timeout.tv_sec = 0; + total_timeout.tv_usec = 0; + while (scanf("%s", s) != EOF) { + clnt_stat = clnt_call(client, RENDERSTRING_BATCHED, + xdr_wrapstring, &s, NULL, NULL, total_timeout); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(client, "batched rpc"); + exit(-1); + } + } + + /* \fINow flush the pipeline\fP */ + + total_timeout.tv_sec = 20; + clnt_stat = clnt_call(client, NULLPROC, xdr_void, NULL, + xdr_void, NULL, total_timeout); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(client, "rpc"); + exit(-1); + } + clnt_destroy(client); + exit(0); +} +.vs +.DE +.KE +Since the server sends no message, +the clients cannot be notified of any of the failures that may occur. +Therefore, clients are on their own when it comes to handling errors. +.LP +The above example was completed to render +all of the (2000) lines in the file +.I /etc/termcap . +The rendering service did nothing but throw the lines away. +The example was run in the following four configurations: +1) machine to itself, regular RPC; +2) machine to itself, batched RPC; +3) machine to another, regular RPC; and +4) machine to another, batched RPC. +The results are as follows: +1) 50 seconds; +2) 16 seconds; +3) 52 seconds; +4) 10 seconds. +Running +.I fscanf() +on +.I /etc/termcap +only requires six seconds. +These timings show the advantage of protocols +that allow for overlapped execution, +though these protocols are often hard to design. +.NH 2 +\&Authentication +.IX "authentication" +.IX "RPC" "authentication" +.LP +In the examples presented so far, +the caller never identified itself to the server, +and the server never required an ID from the caller. +Clearly, some network services, such as a network filesystem, +require stronger security than what has been presented so far. +.LP +In reality, every RPC call is authenticated by +the RPC package on the server, and similarly, +the RPC client package generates and sends authentication parameters. +Just as different transports (TCP/IP or UDP/IP) +can be used when creating RPC clients and servers, +different forms of authentication can be associated with RPC clients; +the default authentication type used as a default is type +.I none . +.LP +The authentication subsystem of the RPC package is open ended. +That is, numerous types of authentication are easy to support. +.NH 3 +\&UNIX Authentication +.IX "UNIX Authentication" +.IP "\fIThe Client Side\fP" +.LP +When a caller creates a new RPC client handle as in: +.DS +.ft CW +clnt = clntudp_create(address, prognum, versnum, + wait, sockp) +.DE +the appropriate transport instance defaults +the associate authentication handle to be +.DS +.ft CW +clnt->cl_auth = authnone_create(); +.DE +The RPC client can choose to use +.I UNIX +style authentication by setting +.I clnt\->cl_auth +after creating the RPC client handle: +.DS +.ft CW +clnt->cl_auth = authunix_create_default(); +.DE +This causes each RPC call associated with +.I clnt +to carry with it the following authentication credentials structure: +.ie t .DS +.el .DS L +.ft I +/* + * UNIX style credentials. + */ +.ft CW +struct authunix_parms { + u_long aup_time; /* \fIcredentials creation time\fP */ + char *aup_machname; /* \fIhost name where client is\fP */ + int aup_uid; /* \fIclient's UNIX effective uid\fP */ + int aup_gid; /* \fIclient's current group id\fP */ + u_int aup_len; /* \fIelement length of aup_gids\fP */ + int *aup_gids; /* \fIarray of groups user is in\fP */ +}; +.DE +These fields are set by +.I authunix_create_default() +by invoking the appropriate system calls. +Since the RPC user created this new style of authentication, +the user is responsible for destroying it with: +.DS +.ft CW +auth_destroy(clnt->cl_auth); +.DE +This should be done in all cases, to conserve memory. +.sp +.IP "\fIThe Server Side\fP" +.LP +Service implementors have a harder time dealing with authentication issues +since the RPC package passes the service dispatch routine a request +that has an arbitrary authentication style associated with it. +Consider the fields of a request handle passed to a service dispatch routine: +.ie t .DS +.el .DS L +.ft I +/* + * An RPC Service request + */ +.ft CW +struct svc_req { + u_long rq_prog; /* \fIservice program number\fP */ + u_long rq_vers; /* \fIservice protocol vers num\fP */ + u_long rq_proc; /* \fIdesired procedure number\fP */ + struct opaque_auth rq_cred; /* \fIraw credentials from wire\fP */ + caddr_t rq_clntcred; /* \fIcredentials (read only)\fP */ +}; +.DE +The +.I rq_cred +is mostly opaque, except for one field of interest: +the style or flavor of authentication credentials: +.ie t .DS +.el .DS L +.ft I +/* + * Authentication info. Mostly opaque to the programmer. + */ +.ft CW +struct opaque_auth { + enum_t oa_flavor; /* \fIstyle of credentials\fP */ + caddr_t oa_base; /* \fIaddress of more auth stuff\fP */ + u_int oa_length; /* \fInot to exceed \fIMAX_AUTH_BYTES */ +}; +.DE +.IX RPC guarantees +The RPC package guarantees the following +to the service dispatch routine: +.IP 1. +That the request's +.I rq_cred +is well formed. Thus the service implementor may inspect the request's +.I rq_cred.oa_flavor +to determine which style of authentication the caller used. +The service implementor may also wish to inspect the other fields of +.I rq_cred +if the style is not one of the styles supported by the RPC package. +.IP 2. +That the request's +.I rq_clntcred +field is either +.I NULL +or points to a well formed structure +that corresponds to a supported style of authentication credentials. +Remember that only +.I unix +style is currently supported, so (currently) +.I rq_clntcred +could be cast to a pointer to an +.I authunix_parms +structure. If +.I rq_clntcred +is +.I NULL , +the service implementor may wish to inspect the other (opaque) fields of +.I rq_cred +in case the service knows about a new type of authentication +that the RPC package does not know about. +.LP +Our remote users service example can be extended so that +it computes results for all users except UID 16: +.ie t .DS +.el .DS L +.ft CW +.vs 11 +nuser(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + struct authunix_parms *unix_cred; + int uid; + unsigned long nusers; + +.ft I + /* + * we don't care about authentication for null proc + */ +.ft CW + if (rqstp->rq_proc == NULLPROC) { + if (!svc_sendreply(transp, xdr_void, 0)) { + fprintf(stderr, "can't reply to RPC call\en"); + return (1); + } + return; + } +.ft I + /* + * now get the uid + */ +.ft CW + switch (rqstp->rq_cred.oa_flavor) { + case AUTH_UNIX: + unix_cred = + (struct authunix_parms *)rqstp->rq_clntcred; + uid = unix_cred->aup_uid; + break; + case AUTH_NULL: + default: + svcerr_weakauth(transp); + return; + } + switch (rqstp->rq_proc) { + case RUSERSPROC_NUM: +.ft I + /* + * make sure caller is allowed to call this proc + */ +.ft CW + if (uid == 16) { + svcerr_systemerr(transp); + return; + } +.ft I + /* + * Code here to compute the number of users + * and assign it to the variable \fInusers\fP + */ +.ft CW + if (!svc_sendreply(transp, xdr_u_long, &nusers)) { + fprintf(stderr, "can't reply to RPC call\en"); + return (1); + } + return; + default: + svcerr_noproc(transp); + return; + } +} +.vs +.DE +A few things should be noted here. +First, it is customary not to check +the authentication parameters associated with the +.I NULLPROC +(procedure number zero). +Second, if the authentication parameter's type is not suitable +for your service, you should call +.I svcerr_weakauth() . +And finally, the service protocol itself should return status +for access denied; in the case of our example, the protocol +does not have such a status, so we call the service primitive +.I svcerr_systemerr() +instead. +.LP +The last point underscores the relation between +the RPC authentication package and the services; +RPC deals only with +.I authentication +and not with individual services' +.I "access control" . +The services themselves must implement their own access control policies +and reflect these policies as return statuses in their protocols. +.NH 2 +\&DES Authentication +.IX RPC DES +.IX RPC authentication +.LP +UNIX authentication is quite easy to defeat. Instead of using +.I authunix_create_default (), +one can call +.I authunix_create() +and then modify the RPC authentication handle it returns by filling in +whatever user ID and hostname they wish the server to think they have. +DES authentication is thus recommended for people who want more security +than UNIX authentication offers. +.LP +The details of the DES authentication protocol are complicated and +are not explained here. +See +.I "Remote Procedure Calls: Protocol Specification" +for the details. +.LP +In order for DES authentication to work, the +.I keyserv(8c) +daemon must be running on both the server and client machines. The +users on these machines need public keys assigned by the network +administrator in the +.I publickey(5) +database. And, they need to have decrypted their secret keys +using their login password. This automatically happens when one +logs in using +.I login(1) , +or can be done manually using +.I keylogin(1) . +The +.I "Network Services" +chapter +./" XXX +explains more how to setup secure networking. +.sp +.IP "\fIClient Side\fP" +.LP +If a client wishes to use DES authentication, it must set its +authentication handle appropriately. Here is an example: +.DS +cl->cl_auth = + authdes_create(servername, 60, &server_addr, NULL); +.DE +The first argument is the network name or \*Qnetname\*U of the owner of +the server process. Typically, server processes are root processes +and their netname can be derived using the following call: +.DS +char servername[MAXNETNAMELEN]; + +host2netname(servername, rhostname, NULL); +.DE +Here, +.I rhostname +is the hostname of the machine the server process is running on. +.I host2netname() +fills in +.I servername +to contain this root process's netname. If the +server process was run by a regular user, one could use the call +.I user2netname() +instead. Here is an example for a server process with the same user +ID as the client: +.DS +char servername[MAXNETNAMELEN]; + +user2netname(servername, getuid(), NULL); +.DE +The last argument to both of these calls, +.I user2netname() +and +.I host2netname (), +is the name of the naming domain where the server is located. The +.I NULL +used here means \*Quse the local domain name.\*U +.LP +The second argument to +.I authdes_create() +is a lifetime for the credential. Here it is set to sixty +seconds. What that means is that the credential will expire 60 +seconds from now. If some mischievous user tries to reuse the +credential, the server RPC subsystem will recognize that it has +expired and not grant any requests. If the same mischievous user +tries to reuse the credential within the sixty second lifetime, +he will still be rejected because the server RPC subsystem +remembers which credentials it has already seen in the near past, +and will not grant requests to duplicates. +.LP +The third argument to +.I authdes_create() +is the address of the host to synchronize with. In order for DES +authentication to work, the server and client must agree upon the +time. Here we pass the address of the server itself, so the +client and server will both be using the same time: the server's +time. The argument can be +.I NULL , +which means \*Qdon't bother synchronizing.\*U You should only do this +if you are sure the client and server are already synchronized. +.LP +The final argument to +.I authdes_create() +is the address of a DES encryption key to use for encrypting +timestamps and data. If this argument is +.I NULL , +as it is in this example, a random key will be chosen. The client +may find out the encryption key being used by consulting the +.I ah_key +field of the authentication handle. +.sp +.IP "\fIServer Side\fP" +.LP +The server side is a lot simpler than the client side. Here is the +previous example rewritten to use +.I AUTH_DES +instead of +.I AUTH_UNIX : +.ie t .DS +.el .DS L +.ft CW +.vs 11 +#include +#include + . . . + . . . +nuser(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + struct authdes_cred *des_cred; + int uid; + int gid; + int gidlen; + int gidlist[10]; +.ft I + /* + * we don't care about authentication for null proc + */ +.ft CW + + if (rqstp->rq_proc == NULLPROC) { + /* \fIsame as before\fP */ + } + +.ft I + /* + * now get the uid + */ +.ft CW + switch (rqstp->rq_cred.oa_flavor) { + case AUTH_DES: + des_cred = + (struct authdes_cred *) rqstp->rq_clntcred; + if (! netname2user(des_cred->adc_fullname.name, + &uid, &gid, &gidlen, gidlist)) + { + fprintf(stderr, "unknown user: %s\n", + des_cred->adc_fullname.name); + svcerr_systemerr(transp); + return; + } + break; + case AUTH_NULL: + default: + svcerr_weakauth(transp); + return; + } + +.ft I + /* + * The rest is the same as before + */ +.ft CW +.vs +.DE +Note the use of the routine +.I netname2user (), +the inverse of +.I user2netname (): +it takes a network ID and converts to a unix ID. +.I netname2user () +also supplies the group IDs which we don't use in this example, +but which may be useful to other UNIX programs. +.NH 2 +\&Using Inetd +.IX inetd "" "using \fIinetd\fP" +.LP +An RPC server can be started from +.I inetd +The only difference from the usual code is that the service +creation routine should be called in the following form: +.ie t .DS +.el .DS L +.ft CW +transp = svcudp_create(0); /* \fIFor UDP\fP */ +transp = svctcp_create(0,0,0); /* \fIFor listener TCP sockets\fP */ +transp = svcfd_create(0,0,0); /* \fIFor connected TCP sockets\fP */ +.DE +since +.I inet +passes a socket as file descriptor 0. +Also, +.I svc_register() +should be called as +.ie t .DS +.el .DS L +.ft CW +svc_register(transp, PROGNUM, VERSNUM, service, 0); +.DE +with the final flag as 0, +since the program would already be registered by +.I inetd +Remember that if you want to exit +from the server process and return control to +.I inet +you need to explicitly exit, since +.I svc_run() +never returns. +.LP +The format of entries in +.I /etc/inetd.conf +for RPC services is in one of the following two forms: +.ie t .DS +.el .DS L +.ft CW +p_name/version dgram rpc/udp wait/nowait user server args +p_name/version stream rpc/tcp wait/nowait user server args +.DE +where +.I p_name +is the symbolic name of the program as it appears in +.I rpc(5) , +.I server +is the program implementing the server, +and +.I program +and +.I version +are the program and version numbers of the service. +For more information, see +.I inetd.conf(5) . +.LP +If the same program handles multiple versions, +then the version number can be a range, +as in this example: +.ie t .DS +.el .DS L +.ft CW +rstatd/1-2 dgram rpc/udp wait root /usr/etc/rpc.rstatd +.DE +.NH 1 +\&More Examples +.sp 1 +.NH 2 +\&Versions +.IX "versions" +.IX "RPC" "versions" +.LP +By convention, the first version number of program +.I PROG +is +.I PROGVERS_ORIG +and the most recent version is +.I PROGVERS +Suppose there is a new version of the +.I user +program that returns an +.I "unsigned short" +rather than a +.I long . +If we name this version +.I RUSERSVERS_SHORT +then a server that wants to support both versions +would do a double register. +.ie t .DS +.el .DS L +.ft CW +if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG, + nuser, IPPROTO_TCP)) { + fprintf(stderr, "can't register RUSER service\en"); + exit(1); +} +if (!svc_register(transp, RUSERSPROG, RUSERSVERS_SHORT, + nuser, IPPROTO_TCP)) { + fprintf(stderr, "can't register RUSER service\en"); + exit(1); +} +.DE +Both versions can be handled by the same C procedure: +.ie t .DS +.el .DS L +.ft CW +.vs 11 +nuser(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + unsigned long nusers; + unsigned short nusers2; + + switch (rqstp->rq_proc) { + case NULLPROC: + if (!svc_sendreply(transp, xdr_void, 0)) { + fprintf(stderr, "can't reply to RPC call\en"); + return (1); + } + return; + case RUSERSPROC_NUM: +.ft I + /* + * Code here to compute the number of users + * and assign it to the variable \fInusers\fP + */ +.ft CW + nusers2 = nusers; + switch (rqstp->rq_vers) { + case RUSERSVERS_ORIG: + if (!svc_sendreply(transp, xdr_u_long, + &nusers)) { + fprintf(stderr,"can't reply to RPC call\en"); + } + break; + case RUSERSVERS_SHORT: + if (!svc_sendreply(transp, xdr_u_short, + &nusers2)) { + fprintf(stderr,"can't reply to RPC call\en"); + } + break; + } + default: + svcerr_noproc(transp); + return; + } +} +.vs +.DE +.KS +.NH 2 +\&TCP +.IX "TCP" +.LP +Here is an example that is essentially +.I rcp. +The initiator of the RPC +.I snd +call takes its standard input and sends it to the server +.I rcv +which prints it on standard output. +The RPC call uses TCP. +This also illustrates an XDR procedure that behaves differently +on serialization than on deserialization. +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * The xdr routine: + * on decode, read from wire, write onto fp + * on encode, read from fp, write onto wire + */ +.ft CW +#include +#include + +xdr_rcp(xdrs, fp) + XDR *xdrs; + FILE *fp; +{ + unsigned long size; + char buf[BUFSIZ], *p; + + if (xdrs->x_op == XDR_FREE)/* nothing to free */ + return 1; + while (1) { + if (xdrs->x_op == XDR_ENCODE) { + if ((size = fread(buf, sizeof(char), BUFSIZ, + fp)) == 0 && ferror(fp)) { + fprintf(stderr, "can't fread\en"); + return (1); + } + } + p = buf; + if (!xdr_bytes(xdrs, &p, &size, BUFSIZ)) + return 0; + if (size == 0) + return 1; + if (xdrs->x_op == XDR_DECODE) { + if (fwrite(buf, sizeof(char), size, + fp) != size) { + fprintf(stderr, "can't fwrite\en"); + return (1); + } + } + } +} +.vs +.DE +.KE +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * The sender routines + */ +.ft CW +#include +#include +#include +#include +#include + +main(argc, argv) + int argc; + char **argv; +{ + int xdr_rcp(); + int err; + + if (argc < 2) { + fprintf(stderr, "usage: %s servername\en", argv[0]); + exit(-1); + } + if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC, + RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) { + clnt_perrno(err); + fprintf(stderr, "can't make RPC call\en"); + exit(1); + } + exit(0); +} + +callrpctcp(host, prognum, procnum, versnum, + inproc, in, outproc, out) + char *host, *in, *out; + xdrproc_t inproc, outproc; +{ + struct sockaddr_in server_addr; + int socket = RPC_ANYSOCK; + enum clnt_stat clnt_stat; + struct hostent *hp; + register CLIENT *client; + struct timeval total_timeout; + + if ((hp = gethostbyname(host)) == NULL) { + fprintf(stderr, "can't get addr for '%s'\en", host); + return (-1); + } + bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, + hp->h_length); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + if ((client = clnttcp_create(&server_addr, prognum, + versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) { + perror("rpctcp_create"); + return (-1); + } + total_timeout.tv_sec = 20; + total_timeout.tv_usec = 0; + clnt_stat = clnt_call(client, procnum, + inproc, in, outproc, out, total_timeout); + clnt_destroy(client); + return (int)clnt_stat; +} +.vs +.DE +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * The receiving routines + */ +.ft CW +#include +#include + +main() +{ + register SVCXPRT *transp; + int rcp_service(), xdr_rcp(); + + if ((transp = svctcp_create(RPC_ANYSOCK, + BUFSIZ, BUFSIZ)) == NULL) { + fprintf("svctcp_create: error\en"); + exit(1); + } + pmap_unset(RCPPROG, RCPVERS); + if (!svc_register(transp, + RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) { + fprintf(stderr, "svc_register: error\en"); + exit(1); + } + svc_run(); /* \fInever returns\fP */ + fprintf(stderr, "svc_run should never return\en"); +} + +rcp_service(rqstp, transp) + register struct svc_req *rqstp; + register SVCXPRT *transp; +{ + switch (rqstp->rq_proc) { + case NULLPROC: + if (svc_sendreply(transp, xdr_void, 0) == 0) { + fprintf(stderr, "err: rcp_service"); + return (1); + } + return; + case RCPPROC_FP: + if (!svc_getargs(transp, xdr_rcp, stdout)) { + svcerr_decode(transp); + return; + } + if (!svc_sendreply(transp, xdr_void, 0)) { + fprintf(stderr, "can't reply\en"); + return; + } + return (0); + default: + svcerr_noproc(transp); + return; + } +} +.vs +.DE +.NH 2 +\&Callback Procedures +.IX RPC "callback procedures" +.LP +Occasionally, it is useful to have a server become a client, +and make an RPC call back to the process which is its client. +An example is remote debugging, +where the client is a window system program, +and the server is a debugger running on the remote machine. +Most of the time, +the user clicks a mouse button at the debugging window, +which converts this to a debugger command, +and then makes an RPC call to the server +(where the debugger is actually running), +telling it to execute that command. +However, when the debugger hits a breakpoint, the roles are reversed, +and the debugger wants to make an rpc call to the window program, +so that it can inform the user that a breakpoint has been reached. +.LP +In order to do an RPC callback, +you need a program number to make the RPC call on. +Since this will be a dynamically generated program number, +it should be in the transient range, +.I "0x40000000 - 0x5fffffff" . +The routine +.I gettransient() +returns a valid program number in the transient range, +and registers it with the portmapper. +It only talks to the portmapper running on the same machine as the +.I gettransient() +routine itself. The call to +.I pmap_set() +is a test and set operation, +in that it indivisibly tests whether a program number +has already been registered, +and if it has not, then reserves it. On return, the +.I sockp +argument will contain a socket that can be used +as the argument to an +.I svcudp_create() +or +.I svctcp_create() +call. +.ie t .DS +.el .DS L +.ft CW +.vs 11 +#include +#include +#include + +gettransient(proto, vers, sockp) + int proto, vers, *sockp; +{ + static int prognum = 0x40000000; + int s, len, socktype; + struct sockaddr_in addr; + + switch(proto) { + case IPPROTO_UDP: + socktype = SOCK_DGRAM; + break; + case IPPROTO_TCP: + socktype = SOCK_STREAM; + break; + default: + fprintf(stderr, "unknown protocol type\en"); + return 0; + } + if (*sockp == RPC_ANYSOCK) { + if ((s = socket(AF_INET, socktype, 0)) < 0) { + perror("socket"); + return (0); + } + *sockp = s; + } + else + s = *sockp; + addr.sin_addr.s_addr = 0; + addr.sin_family = AF_INET; + addr.sin_port = 0; + len = sizeof(addr); +.ft I + /* + * may be already bound, so don't check for error + */ +.ft CW + bind(s, &addr, len); + if (getsockname(s, &addr, &len)< 0) { + perror("getsockname"); + return (0); + } + while (!pmap_set(prognum++, vers, proto, + ntohs(addr.sin_port))) continue; + return (prognum-1); +} +.vs +.DE +.SH +Note: +.I +The call to +.I ntohs() +is necessary to ensure that the port number in +.I "addr.sin_port" , +which is in +.I network +byte order, is passed in +.I host +byte order (as +.I pmap_set() +expects). See the +.I byteorder(3N) +man page for more details on the conversion of network +addresses from network to host byte order. +.KS +.LP +The following pair of programs illustrate how to use the +.I gettransient() +routine. +The client makes an RPC call to the server, +passing it a transient program number. +Then the client waits around to receive a callback +from the server at that program number. +The server registers the program +.I EXAMPLEPROG +so that it can receive the RPC call +informing it of the callback program number. +Then at some random time (on receiving an +.I ALRM +signal in this example), it sends a callback RPC call, +using the program number it received earlier. +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * client + */ +.ft CW +#include +#include + +int callback(); +char hostname[256]; + +main() +{ + int x, ans, s; + SVCXPRT *xprt; + + gethostname(hostname, sizeof(hostname)); + s = RPC_ANYSOCK; + x = gettransient(IPPROTO_UDP, 1, &s); + fprintf(stderr, "client gets prognum %d\en", x); + if ((xprt = svcudp_create(s)) == NULL) { + fprintf(stderr, "rpc_server: svcudp_create\en"); + exit(1); + } +.ft I + /* protocol is 0 - gettransient does registering + */ +.ft CW + (void)svc_register(xprt, x, 1, callback, 0); + ans = callrpc(hostname, EXAMPLEPROG, EXAMPLEVERS, + EXAMPLEPROC_CALLBACK, xdr_int, &x, xdr_void, 0); + if ((enum clnt_stat) ans != RPC_SUCCESS) { + fprintf(stderr, "call: "); + clnt_perrno(ans); + fprintf(stderr, "\en"); + } + svc_run(); + fprintf(stderr, "Error: svc_run shouldn't return\en"); +} + +callback(rqstp, transp) + register struct svc_req *rqstp; + register SVCXPRT *transp; +{ + switch (rqstp->rq_proc) { + case 0: + if (!svc_sendreply(transp, xdr_void, 0)) { + fprintf(stderr, "err: exampleprog\en"); + return (1); + } + return (0); + case 1: + if (!svc_getargs(transp, xdr_void, 0)) { + svcerr_decode(transp); + return (1); + } + fprintf(stderr, "client got callback\en"); + if (!svc_sendreply(transp, xdr_void, 0)) { + fprintf(stderr, "err: exampleprog"); + return (1); + } + } +} +.vs +.DE +.KE +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * server + */ +.ft CW +#include +#include +#include + +char *getnewprog(); +char hostname[256]; +int docallback(); +int pnum; /* \fIprogram number for callback routine\fP */ + +main() +{ + gethostname(hostname, sizeof(hostname)); + registerrpc(EXAMPLEPROG, EXAMPLEVERS, + EXAMPLEPROC_CALLBACK, getnewprog, xdr_int, xdr_void); + fprintf(stderr, "server going into svc_run\en"); + signal(SIGALRM, docallback); + alarm(10); + svc_run(); + fprintf(stderr, "Error: svc_run shouldn't return\en"); +} + +char * +getnewprog(pnump) + char *pnump; +{ + pnum = *(int *)pnump; + return NULL; +} + +docallback() +{ + int ans; + + ans = callrpc(hostname, pnum, 1, 1, xdr_void, 0, + xdr_void, 0); + if (ans != 0) { + fprintf(stderr, "server: "); + clnt_perrno(ans); + fprintf(stderr, "\en"); + } +} +.vs +.DE diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/rpc.rfc.ms b/c/src/exec/librpc/src/rpc/PSD.doc/rpc.rfc.ms index e69de29bb2..af9c2df2ed 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/rpc.rfc.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/rpc.rfc.ms @@ -0,0 +1,1302 @@ +.\" +.\" Must use -- tbl -- with this one +.\" +.\" @(#)rpc.rfc.ms 2.2 88/08/05 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'Remote Procedure Calls: Protocol Specification''Page %' +.EH 'Page %''Remote Procedure Calls: Protocol Specification' +.if \\n%=1 .bp +.SH +\&Remote Procedure Calls: Protocol Specification +.LP +.NH 0 +\&Status of this Memo +.LP +Note: This chapter specifies a protocol that Sun Microsystems, Inc., +and others are using. +It has been designated RFC1050 by the ARPA Network +Information Center. +.LP +.NH 1 +\&Introduction +.LP +This chapter specifies a message protocol used in implementing +Sun's Remote Procedure Call (RPC) package. (The message protocol is +specified with the External Data Representation (XDR) language. +See the +.I "External Data Representation Standard: Protocol Specification" +for the details. Here, we assume that the reader is familiar +with XDR and do not attempt to justify it or its uses). The paper +by Birrell and Nelson [1] is recommended as an excellent background +to and justification of RPC. +.NH 2 +\&Terminology +.LP +This chapter discusses servers, services, programs, procedures, +clients, and versions. A server is a piece of software where network +services are implemented. A network service is a collection of one +or more remote programs. A remote program implements one or more +remote procedures; the procedures, their parameters, and results are +documented in the specific program's protocol specification (see the +\fIPort Mapper Program Protocol\fP\, below, for an example). Network +clients are pieces of software that initiate remote procedure calls +to services. A server may support more than one version of a remote +program in order to be forward compatible with changing protocols. +.LP +For example, a network file service may be composed of two programs. +One program may deal with high-level applications such as file system +access control and locking. The other may deal with low-level file +IO and have procedures like "read" and "write". A client machine of +the network file service would call the procedures associated with +the two programs of the service on behalf of some user on the client +machine. +.NH 2 +\&The RPC Model +.LP +The remote procedure call model is similar to the local procedure +call model. In the local case, the caller places arguments to a +procedure in some well-specified location (such as a result +register). It then transfers control to the procedure, and +eventually gains back control. At that point, the results of the +procedure are extracted from the well-specified location, and the +caller continues execution. +.LP +The remote procedure call is similar, in that one thread of control +logically winds through two processes\(emone is the caller's process, +the other is a server's process. That is, the caller process sends a +call message to the server process and waits (blocks) for a reply +message. The call message contains the procedure's parameters, among +other things. The reply message contains the procedure's results, +among other things. Once the reply message is received, the results +of the procedure are extracted, and caller's execution is resumed. +.LP +On the server side, a process is dormant awaiting the arrival of a +call message. When one arrives, the server process extracts the +procedure's parameters, computes the results, sends a reply message, +and then awaits the next call message. +.LP +Note that in this model, only one of the two processes is active at +any given time. However, this model is only given as an example. +The RPC protocol makes no restrictions on the concurrency model +implemented, and others are possible. For example, an implementation +may choose to have RPC calls be asynchronous, so that the client may +do useful work while waiting for the reply from the server. Another +possibility is to have the server create a task to process an +incoming request, so that the server can be free to receive other +requests. +.NH 2 +\&Transports and Semantics +.LP +The RPC protocol is independent of transport protocols. That is, RPC +does not care how a message is passed from one process to another. +The protocol deals only with specification and interpretation of +messages. +.LP +It is important to point out that RPC does not try to implement any +kind of reliability and that the application must be aware of the +type of transport protocol underneath RPC. If it knows it is running +on top of a reliable transport such as TCP/IP[6], then most of the +work is already done for it. On the other hand, if it is running on +top of an unreliable transport such as UDP/IP[7], it must implement +is own retransmission and time-out policy as the RPC layer does not +provide this service. +.LP +Because of transport independence, the RPC protocol does not attach +specific semantics to the remote procedures or their execution. +Semantics can be inferred from (but should be explicitly specified +by) the underlying transport protocol. For example, consider RPC +running on top of an unreliable transport such as UDP/IP. If an +application retransmits RPC messages after short time-outs, the only +thing it can infer if it receives no reply is that the procedure was +executed zero or more times. If it does receive a reply, then it can +infer that the procedure was executed at least once. +.LP +A server may wish to remember previously granted requests from a +client and not regrant them in order to insure some degree of +execute-at-most-once semantics. A server can do this by taking +advantage of the transaction ID that is packaged with every RPC +request. The main use of this transaction is by the client RPC layer +in matching replies to requests. However, a client application may +choose to reuse its previous transaction ID when retransmitting a +request. The server application, knowing this fact, may choose to +remember this ID after granting a request and not regrant requests +with the same ID in order to achieve some degree of +execute-at-most-once semantics. The server is not allowed to examine +this ID in any other way except as a test for equality. +.LP +On the other hand, if using a reliable transport such as TCP/IP, the +application can infer from a reply message that the procedure was +executed exactly once, but if it receives no reply message, it cannot +assume the remote procedure was not executed. Note that even if a +connection-oriented protocol like TCP is used, an application still +needs time-outs and reconnection to handle server crashes. +.LP +There are other possibilities for transports besides datagram- or +connection-oriented protocols. For example, a request-reply protocol +such as VMTP[2] is perhaps the most natural transport for RPC. +.SH +.I +NOTE: At Sun, RPC is currently implemented on top of both TCP/IP +and UDP/IP transports. +.LP +.NH 2 +\&Binding and Rendezvous Independence +.LP +The act of binding a client to a service is NOT part of the remote +procedure call specification. This important and necessary function +is left up to some higher-level software. (The software may use RPC +itself\(emsee the \fIPort Mapper Program Protocol\fP\, below). +.LP +Implementors should think of the RPC protocol as the jump-subroutine +instruction ("JSR") of a network; the loader (binder) makes JSR +useful, and the loader itself uses JSR to accomplish its task. +Likewise, the network makes RPC useful, using RPC to accomplish this +task. +.NH 2 +\&Authentication +.LP +The RPC protocol provides the fields necessary for a client to +identify itself to a service and vice-versa. Security and access +control mechanisms can be built on top of the message authentication. +Several different authentication protocols can be supported. A field +in the RPC header indicates which protocol is being used. More +information on specific authentication protocols can be found in the +\fIAuthentication Protocols\fP\, +below. +.KS +.NH 1 +\&RPC Protocol Requirements +.LP +The RPC protocol must provide for the following: +.IP 1. +Unique specification of a procedure to be called. +.IP 2. +Provisions for matching response messages to request messages. +.KE +.IP 3. +Provisions for authenticating the caller to service and vice-versa. +.LP +Besides these requirements, features that detect the following are +worth supporting because of protocol roll-over errors, implementation +bugs, user error, and network administration: +.IP 1. +RPC protocol mismatches. +.IP 2. +Remote program protocol version mismatches. +.IP 3. +Protocol errors (such as misspecification of a procedure's parameters). +.IP 4. +Reasons why remote authentication failed. +.IP 5. +Any other reasons why the desired procedure was not called. +.NH 2 +\&Programs and Procedures +.LP +The RPC call message has three unsigned fields: remote program +number, remote program version number, and remote procedure number. +The three fields uniquely identify the procedure to be called. +Program numbers are administered by some central authority (like +Sun). Once an implementor has a program number, he can implement his +remote program; the first implementation would most likely have the +version number of 1. Because most new protocols evolve into better, +stable, and mature protocols, a version field of the call message +identifies which version of the protocol the caller is using. +Version numbers make speaking old and new protocols through the same +server process possible. +.LP +The procedure number identifies the procedure to be called. These +numbers are documented in the specific program's protocol +specification. For example, a file service's protocol specification +may state that its procedure number 5 is "read" and procedure number +12 is "write". +.LP +Just as remote program protocols may change over several versions, +the actual RPC message protocol could also change. Therefore, the +call message also has in it the RPC version number, which is always +equal to two for the version of RPC described here. +.LP +The reply message to a request message has enough information to +distinguish the following error conditions: +.IP 1. +The remote implementation of RPC does speak protocol version 2. +The lowest and highest supported RPC version numbers are returned. +.IP 2. +The remote program is not available on the remote system. +.IP 3. +The remote program does not support the requested version number. +The lowest and highest supported remote program version numbers are +returned. +.IP 4. +The requested procedure number does not exist. (This is usually a +caller side protocol or programming error.) +.IP 5. +The parameters to the remote procedure appear to be garbage from the +server's point of view. (Again, this is usually caused by a +disagreement about the protocol between client and service.) +.NH 2 +\&Authentication +.LP +Provisions for authentication of caller to service and vice-versa are +provided as a part of the RPC protocol. The call message has two +authentication fields, the credentials and verifier. The reply +message has one authentication field, the response verifier. The RPC +protocol specification defines all three fields to be the following +opaque type: +.DS +.ft CW +.vs 11 +enum auth_flavor { + AUTH_NULL = 0, + AUTH_UNIX = 1, + AUTH_SHORT = 2, + AUTH_DES = 3 + /* \fIand more to be defined\fP */ +}; + +struct opaque_auth { + auth_flavor flavor; + opaque body<400>; +}; +.DE +.LP +In simple English, any +.I opaque_auth +structure is an +.I auth_flavor +enumeration followed by bytes which are opaque to the RPC protocol +implementation. +.LP +The interpretation and semantics of the data contained within the +authentication fields is specified by individual, independent +authentication protocol specifications. (See +\fIAuthentication Protocols\fP\, +below, for definitions of the various authentication protocols.) +.LP +If authentication parameters were rejected, the response message +contains information stating why they were rejected. +.NH 2 +\&Program Number Assignment +.LP +Program numbers are given out in groups of +.I 0x20000000 +(decimal 536870912) according to the following chart: +.TS +box tab (&) ; +lfI lfI +rfL cfI . +Program Numbers&Description +_ +.sp .5 +0 - 1fffffff&Defined by Sun +20000000 - 3fffffff&Defined by user +40000000 - 5fffffff&Transient +60000000 - 7fffffff&Reserved +80000000 - 9fffffff&Reserved +a0000000 - bfffffff&Reserved +c0000000 - dfffffff&Reserved +e0000000 - ffffffff&Reserved +.TE +.LP +The first group is a range of numbers administered by Sun +Microsystems and should be identical for all sites. The second range +is for applications peculiar to a particular site. This range is +intended primarily for debugging new programs. When a site develops +an application that might be of general interest, that application +should be given an assigned number in the first range. The third +group is for applications that generate program numbers dynamically. +The final groups are reserved for future use, and should not be used. +.NH 2 +\&Other Uses of the RPC Protocol +.LP +The intended use of this protocol is for calling remote procedures. +That is, each call message is matched with a response message. +However, the protocol itself is a message-passing protocol with which +other (non-RPC) protocols can be implemented. Sun currently uses, or +perhaps abuses, the RPC message protocol for the following two +(non-RPC) protocols: batching (or pipelining) and broadcast RPC. +These two protocols are discussed but not defined below. +.NH 3 +\&Batching +.LP +Batching allows a client to send an arbitrarily large sequence of +call messages to a server; batching typically uses reliable byte +stream protocols (like TCP/IP) for its transport. In the case of +batching, the client never waits for a reply from the server, and the +server does not send replies to batch requests. A sequence of batch +calls is usually terminated by a legitimate RPC in order to flush the +pipeline (with positive acknowledgement). +.NH 3 +\&Broadcast RPC +.LP +In broadcast RPC-based protocols, the client sends a broadcast packet +to the network and waits for numerous replies. Broadcast RPC uses +unreliable, packet-based protocols (like UDP/IP) as its transports. +Servers that support broadcast protocols only respond when the +request is successfully processed, and are silent in the face of +errors. Broadcast RPC uses the Port Mapper RPC service to achieve +its semantics. See the \fIPort Mapper Program Protocol\fP\, below, +for more information. +.KS +.NH 1 +\&The RPC Message Protocol +.LP +This section defines the RPC message protocol in the XDR data +description language. The message is defined in a top-down style. +.ie t .DS +.el .DS L +.ft CW +enum msg_type { + CALL = 0, + REPLY = 1 +}; + +.ft I +/* +* A reply to a call message can take on two forms: +* The message was either accepted or rejected. +*/ +.ft CW +enum reply_stat { + MSG_ACCEPTED = 0, + MSG_DENIED = 1 +}; + +.ft I +/* +* Given that a call message was accepted, the following is the +* status of an attempt to call a remote procedure. +*/ +.ft CW +enum accept_stat { + SUCCESS = 0, /* \fIRPC executed successfully \fP*/ + PROG_UNAVAIL = 1, /* \fIremote hasn't exported program \fP*/ + PROG_MISMATCH = 2, /* \fIremote can't support version # \fP*/ + PROC_UNAVAIL = 3, /* \fIprogram can't support procedure \fP*/ + GARBAGE_ARGS = 4 /* \fIprocedure can't decode params \fP*/ +}; +.DE +.ie t .DS +.el .DS L +.ft I +/* +* Reasons why a call message was rejected: +*/ +.ft CW +enum reject_stat { + RPC_MISMATCH = 0, /* \fIRPC version number != 2 \fP*/ + AUTH_ERROR = 1 /* \fIremote can't authenticate caller \fP*/ +}; + +.ft I +/* +* Why authentication failed: +*/ +.ft CW +enum auth_stat { + AUTH_BADCRED = 1, /* \fIbad credentials \fP*/ + AUTH_REJECTEDCRED = 2, /* \fIclient must begin new session \fP*/ + AUTH_BADVERF = 3, /* \fIbad verifier \fP*/ + AUTH_REJECTEDVERF = 4, /* \fIverifier expired or replayed \fP*/ + AUTH_TOOWEAK = 5 /* \fIrejected for security reasons \fP*/ +}; +.DE +.KE +.ie t .DS +.el .DS L +.ft I +/* +* The RPC message: +* All messages start with a transaction identifier, xid, +* followed by a two-armed discriminated union. The union's +* discriminant is a msg_type which switches to one of the two +* types of the message. The xid of a \fIREPLY\fP message always +* matches that of the initiating \fICALL\fP message. NB: The xid +* field is only used for clients matching reply messages with +* call messages or for servers detecting retransmissions; the +* service side cannot treat this id as any type of sequence +* number. +*/ +.ft CW +struct rpc_msg { + unsigned int xid; + union switch (msg_type mtype) { + case CALL: + call_body cbody; + case REPLY: + reply_body rbody; + } body; +}; +.DE +.ie t .DS +.el .DS L +.ft I +/* +* Body of an RPC request call: +* In version 2 of the RPC protocol specification, rpcvers must +* be equal to 2. The fields prog, vers, and proc specify the +* remote program, its version number, and the procedure within +* the remote program to be called. After these fields are two +* authentication parameters: cred (authentication credentials) +* and verf (authentication verifier). The two authentication +* parameters are followed by the parameters to the remote +* procedure, which are specified by the specific program +* protocol. +*/ +.ft CW +struct call_body { + unsigned int rpcvers; /* \fImust be equal to two (2) \fP*/ + unsigned int prog; + unsigned int vers; + unsigned int proc; + opaque_auth cred; + opaque_auth verf; + /* \fIprocedure specific parameters start here \fP*/ +}; +.DE +.ie t .DS +.el .DS L +.ft I +/* +* Body of a reply to an RPC request: +* The call message was either accepted or rejected. +*/ +.ft CW +union reply_body switch (reply_stat stat) { + case MSG_ACCEPTED: + accepted_reply areply; + case MSG_DENIED: + rejected_reply rreply; +} reply; +.DE +.ie t .DS +.el .DS L +.ft I +/* +* Reply to an RPC request that was accepted by the server: +* there could be an error even though the request was accepted. +* The first field is an authentication verifier that the server +* generates in order to validate itself to the caller. It is +* followed by a union whose discriminant is an enum +* accept_stat. The \fISUCCESS\fP arm of the union is protocol +* specific. The \fIPROG_UNAVAIL\fP, \fIPROC_UNAVAIL\fP, and \fIGARBAGE_ARGP\fP +* arms of the union are void. The \fIPROG_MISMATCH\fP arm specifies +* the lowest and highest version numbers of the remote program +* supported by the server. +*/ +.ft CW +struct accepted_reply { + opaque_auth verf; + union switch (accept_stat stat) { + case SUCCESS: + opaque results[0]; + /* \fIprocedure-specific results start here\fP */ + case PROG_MISMATCH: + struct { + unsigned int low; + unsigned int high; + } mismatch_info; + default: +.ft I + /* + * Void. Cases include \fIPROG_UNAVAIL, PROC_UNAVAIL\fP, + * and \fIGARBAGE_ARGS\fP. + */ +.ft CW + void; + } reply_data; +}; +.DE +.ie t .DS +.el .DS L +.ft I +/* +* Reply to an RPC request that was rejected by the server: +* The request can be rejected for two reasons: either the +* server is not running a compatible version of the RPC +* protocol (\fIRPC_MISMATCH\fP), or the server refuses to +* authenticate the caller (\fIAUTH_ERROR\fP). In case of an RPC +* version mismatch, the server returns the lowest and highest +* supported RPC version numbers. In case of refused +* authentication, failure status is returned. +*/ +.ft CW +union rejected_reply switch (reject_stat stat) { + case RPC_MISMATCH: + struct { + unsigned int low; + unsigned int high; + } mismatch_info; + case AUTH_ERROR: + auth_stat stat; +}; +.DE +.NH 1 +\&Authentication Protocols +.LP +As previously stated, authentication parameters are opaque, but +open-ended to the rest of the RPC protocol. This section defines +some "flavors" of authentication implemented at (and supported by) +Sun. Other sites are free to invent new authentication types, with +the same rules of flavor number assignment as there is for program +number assignment. +.NH 2 +\&Null Authentication +.LP +Often calls must be made where the caller does not know who he is or +the server does not care who the caller is. In this case, the flavor +value (the discriminant of the \fIopaque_auth\fP's union) of the RPC +message's credentials, verifier, and response verifier is +.I AUTH_NULL . +The bytes of the opaque_auth's body are undefined. +It is recommended that the opaque length be zero. +.NH 2 +\&UNIX Authentication +.LP +The caller of a remote procedure may wish to identify himself as he +is identified on a UNIX system. The value of the credential's +discriminant of an RPC call message is +.I AUTH_UNIX . +The bytes of +the credential's opaque body encode the following structure: +.DS +.ft CW +struct auth_unix { + unsigned int stamp; + string machinename<255>; + unsigned int uid; + unsigned int gid; + unsigned int gids<10>; +}; +.DE +The +.I stamp +is an arbitrary ID which the caller machine may +generate. The +.I machinename +is the name of the caller's machine (like "krypton"). The +.I uid +is the caller's effective user ID. The +.I gid +is the caller's effective group ID. The +.I gids +is a +counted array of groups which contain the caller as a member. The +verifier accompanying the credentials should be of +.I AUTH_NULL +(defined above). +.LP +The value of the discriminant of the response verifier received in +the reply message from the server may be +.I AUTH_NULL +or +.I AUTH_SHORT . +In the case of +.I AUTH_SHORT , +the bytes of the response verifier's string encode an opaque +structure. This new opaque structure may now be passed to the server +instead of the original +.I AUTH_UNIX +flavor credentials. The server keeps a cache which maps shorthand +opaque structures (passed back by way of an +.I AUTH_SHORT +style response verifier) to the original credentials of the caller. +The caller can save network bandwidth and server cpu cycles by using +the new credentials. +.LP +The server may flush the shorthand opaque structure at any time. If +this happens, the remote procedure call message will be rejected due +to an authentication error. The reason for the failure will be +.I AUTH_REJECTEDCRED . +At this point, the caller may wish to try the original +.I AUTH_UNIX +style of credentials. +.KS +.NH 2 +\&DES Authentication +.LP +UNIX authentication suffers from two major problems: +.IP 1. +The naming is too UNIX-system oriented. +.IP 2. +There is no verifier, so credentials can easily be faked. +.LP +DES authentication attempts to fix these two problems. +.KE +.NH 3 +\&Naming +.LP +The first problem is handled by addressing the caller by a simple +string of characters instead of by an operating system specific +integer. This string of characters is known as the "netname" or +network name of the caller. The server is not allowed to interpret +the contents of the caller's name in any other way except to +identify the caller. Thus, netnames should be unique for every +caller in the internet. +.LP +It is up to each operating system's implementation of DES +authentication to generate netnames for its users that insure this +uniqueness when they call upon remote servers. Operating systems +already know how to distinguish users local to their systems. It is +usually a simple matter to extend this mechanism to the network. +For example, a UNIX user at Sun with a user ID of 515 might be +assigned the following netname: "unix.515@sun.com". This netname +contains three items that serve to insure it is unique. Going +backwards, there is only one naming domain called "sun.com" in the +internet. Within this domain, there is only one UNIX user with +user ID 515. However, there may be another user on another +operating system, for example VMS, within the same naming domain +that, by coincidence, happens to have the same user ID. To insure +that these two users can be distinguished we add the operating +system name. So one user is "unix.515@sun.com" and the other is +"vms.515@sun.com". +.LP +The first field is actually a naming method rather than an +operating system name. It just happens that today there is almost +a one-to-one correspondence between naming methods and operating +systems. If the world could agree on a naming standard, the first +field could be the name of that standard, instead of an operating +system name. +.LP +.NH 3 +\&DES Authentication Verifiers +.LP +Unlike UNIX authentication, DES authentication does have a verifier +so the server can validate the client's credential (and +vice-versa). The contents of this verifier is primarily an +encrypted timestamp. The server can decrypt this timestamp, and if +it is close to what the real time is, then the client must have +encrypted it correctly. The only way the client could encrypt it +correctly is to know the "conversation key" of the RPC session. And +if the client knows the conversation key, then it must be the real +client. +.LP +The conversation key is a DES [5] key which the client generates +and notifies the server of in its first RPC call. The conversation +key is encrypted using a public key scheme in this first +transaction. The particular public key scheme used in DES +authentication is Diffie-Hellman [3] with 192-bit keys. The +details of this encryption method are described later. +.LP +The client and the server need the same notion of the current time +in order for all of this to work. If network time synchronization +cannot be guaranteed, then client can synchronize with the server +before beginning the conversation, perhaps by consulting the +Internet Time Server (TIME[4]). +.LP +The way a server determines if a client timestamp is valid is +somewhat complicated. For any other transaction but the first, the +server just checks for two things: +.IP 1. +the timestamp is greater than the one previously seen from the +same client. +.IP 2. +the timestamp has not expired. +.LP +A timestamp is expired if the server's time is later than the sum +of the client's timestamp plus what is known as the client's +"window". The "window" is a number the client passes (encrypted) +to the server in its first transaction. You can think of it as a +lifetime for the credential. +.LP +This explains everything but the first transaction. In the first +transaction, the server checks only that the timestamp has not +expired. If this was all that was done though, then it would be +quite easy for the client to send random data in place of the +timestamp with a fairly good chance of succeeding. As an added +check, the client sends an encrypted item in the first transaction +known as the "window verifier" which must be equal to the window +minus 1, or the server will reject the credential. +.LP +The client too must check the verifier returned from the server to +be sure it is legitimate. The server sends back to the client the +encrypted timestamp it received from the client, minus one second. +If the client gets anything different than this, it will reject it. +.LP +.NH 3 +\&Nicknames and Clock Synchronization +.LP +After the first transaction, the server's DES authentication +subsystem returns in its verifier to the client an integer +"nickname" which the client may use in its further transactions +instead of passing its netname, encrypted DES key and window every +time. The nickname is most likely an index into a table on the +server which stores for each client its netname, decrypted DES key +and window. +.LP +Though they originally were synchronized, the client's and server's +clocks can get out of sync again. When this happens the client RPC +subsystem most likely will get back +.I RPC_AUTHERROR +at which point it should resynchronize. +.LP +A client may still get the +.I RPC_AUTHERROR +error even though it is +synchronized with the server. The reason is that the server's +nickname table is a limited size, and it may flush entries whenever +it wants. A client should resend its original credential in this +case and the server will give it a new nickname. If a server +crashes, the entire nickname table gets flushed, and all clients +will have to resend their original credentials. +.KS +.NH 3 +\&DES Authentication Protocol (in XDR language) +.ie t .DS +.el .DS L +.ft I +/* +* There are two kinds of credentials: one in which the client uses +* its full network name, and one in which it uses its "nickname" +* (just an unsigned integer) given to it by the server. The +* client must use its fullname in its first transaction with the +* server, in which the server will return to the client its +* nickname. The client may use its nickname in all further +* transactions with the server. There is no requirement to use the +* nickname, but it is wise to use it for performance reasons. +*/ +.ft CW +enum authdes_namekind { + ADN_FULLNAME = 0, + ADN_NICKNAME = 1 +}; + +.ft I +/* +* A 64-bit block of encrypted DES data +*/ +.ft CW +typedef opaque des_block[8]; + +.ft I +/* +* Maximum length of a network user's name +*/ +.ft CW +const MAXNETNAMELEN = 255; + +.ft I +/* +* A fullname contains the network name of the client, an encrypted +* conversation key and the window. The window is actually a +* lifetime for the credential. If the time indicated in the +* verifier timestamp plus the window has past, then the server +* should expire the request and not grant it. To insure that +* requests are not replayed, the server should insist that +* timestamps are greater than the previous one seen, unless it is +* the first transaction. In the first transaction, the server +* checks instead that the window verifier is one less than the +* window. +*/ +.ft CW +struct authdes_fullname { +string name; /* \fIname of client \f(CW*/ +des_block key; /* \fIPK encrypted conversation key \f(CW*/ +unsigned int window; /* \fIencrypted window \f(CW*/ +}; + +.ft I +/* +* A credential is either a fullname or a nickname +*/ +.ft CW +union authdes_cred switch (authdes_namekind adc_namekind) { + case ADN_FULLNAME: + authdes_fullname adc_fullname; + case ADN_NICKNAME: + unsigned int adc_nickname; +}; + +.ft I +/* +* A timestamp encodes the time since midnight, January 1, 1970. +*/ +.ft CW +struct timestamp { + unsigned int seconds; /* \fIseconds \fP*/ + unsigned int useconds; /* \fIand microseconds \fP*/ +}; + +.ft I +/* +* Verifier: client variety +* The window verifier is only used in the first transaction. In +* conjunction with a fullname credential, these items are packed +* into the following structure before being encrypted: +* +* \f(CWstruct {\fP +* \f(CWadv_timestamp; \fP-- one DES block +* \f(CWadc_fullname.window; \fP-- one half DES block +* \f(CWadv_winverf; \fP-- one half DES block +* \f(CW}\fP +* This structure is encrypted using CBC mode encryption with an +* input vector of zero. All other encryptions of timestamps use +* ECB mode encryption. +*/ +.ft CW +struct authdes_verf_clnt { + timestamp adv_timestamp; /* \fIencrypted timestamp \fP*/ + unsigned int adv_winverf; /* \fIencrypted window verifier \fP*/ +}; + +.ft I +/* +* Verifier: server variety +* The server returns (encrypted) the same timestamp the client +* gave it minus one second. It also tells the client its nickname +* to be used in future transactions (unencrypted). +*/ +.ft CW +struct authdes_verf_svr { +timestamp adv_timeverf; /* \fIencrypted verifier \fP*/ +unsigned int adv_nickname; /* \fInew nickname for client \fP*/ +}; +.DE +.KE +.NH 3 +\&Diffie-Hellman Encryption +.LP +In this scheme, there are two constants, +.I BASE +and +.I MODULUS . +The +particular values Sun has chosen for these for the DES +authentication protocol are: +.ie t .DS +.el .DS L +.ft CW +const BASE = 3; +const MODULUS = + "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; /* \fIhex \fP*/ +.DE +.ft R +The way this scheme works is best explained by an example. Suppose +there are two people "A" and "B" who want to send encrypted +messages to each other. So, A and B both generate "secret" keys at +random which they do not reveal to anyone. Let these keys be +represented as SK(A) and SK(B). They also publish in a public +directory their "public" keys. These keys are computed as follows: +.ie t .DS +.el .DS L +.ft CW +PK(A) = ( BASE ** SK(A) ) mod MODULUS +PK(B) = ( BASE ** SK(B) ) mod MODULUS +.DE +.ft R +The "**" notation is used here to represent exponentiation. Now, +both A and B can arrive at the "common" key between them, +represented here as CK(A, B), without revealing their secret keys. +.LP +A computes: +.ie t .DS +.el .DS L +.ft CW +CK(A, B) = ( PK(B) ** SK(A)) mod MODULUS +.DE +.ft R +while B computes: +.ie t .DS +.el .DS L +.ft CW +CK(A, B) = ( PK(A) ** SK(B)) mod MODULUS +.DE +.ft R +These two can be shown to be equivalent: +.ie t .DS +.el .DS L +.ft CW +(PK(B) ** SK(A)) mod MODULUS = (PK(A) ** SK(B)) mod MODULUS +.DE +.ft R +We drop the "mod MODULUS" parts and assume modulo arithmetic to +simplify things: +.ie t .DS +.el .DS L +.ft CW +PK(B) ** SK(A) = PK(A) ** SK(B) +.DE +.ft R +Then, replace PK(B) by what B computed earlier and likewise for +PK(A). +.ie t .DS +.el .DS L +.ft CW +((BASE ** SK(B)) ** SK(A) = (BASE ** SK(A)) ** SK(B) +.DE +.ft R +which leads to: +.ie t .DS +.el .DS L +.ft CW +BASE ** (SK(A) * SK(B)) = BASE ** (SK(A) * SK(B)) +.DE +.ft R +This common key CK(A, B) is not used to encrypt the timestamps used +in the protocol. Rather, it is used only to encrypt a conversation +key which is then used to encrypt the timestamps. The reason for +doing this is to use the common key as little as possible, for fear +that it could be broken. Breaking the conversation key is a far +less serious offense, since conversations are relatively +short-lived. +.LP +The conversation key is encrypted using 56-bit DES keys, yet the +common key is 192 bits. To reduce the number of bits, 56 bits are +selected from the common key as follows. The middle-most 8-bytes +are selected from the common key, and then parity is added to the +lower order bit of each byte, producing a 56-bit key with 8 bits of +parity. +.KS +.NH 1 +\&Record Marking Standard +.LP +When RPC messages are passed on top of a byte stream protocol (like +TCP/IP), it is necessary, or at least desirable, to delimit one +message from another in order to detect and possibly recover from +user protocol errors. This is called record marking (RM). Sun uses +this RM/TCP/IP transport for passing RPC messages on TCP streams. +One RPC message fits into one RM record. +.LP +A record is composed of one or more record fragments. A record +fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of +fragment data. The bytes encode an unsigned binary number; as with +XDR integers, the byte order is from highest to lowest. The number +encodes two values\(ema boolean which indicates whether the fragment +is the last fragment of the record (bit value 1 implies the fragment +is the last fragment) and a 31-bit unsigned binary value which is the +length in bytes of the fragment's data. The boolean value is the +highest-order bit of the header; the length is the 31 low-order bits. +(Note that this record specification is NOT in XDR standard form!) +.KE +.KS +.NH 1 +\&The RPC Language +.LP +Just as there was a need to describe the XDR data-types in a formal +language, there is also need to describe the procedures that operate +on these XDR data-types in a formal language as well. We use the RPC +Language for this purpose. It is an extension to the XDR language. +The following example is used to describe the essence of the +language. +.NH 2 +\&An Example Service Described in the RPC Language +.LP +Here is an example of the specification of a simple ping program. +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* +* Simple ping program +*/ +.ft CW +program PING_PROG { + /* \fILatest and greatest version\fP */ + version PING_VERS_PINGBACK { + void + PINGPROC_NULL(void) = 0; + +.ft I + /* + * Ping the caller, return the round-trip time + * (in microseconds). Returns -1 if the operation + * timed out. + */ +.ft CW + int + PINGPROC_PINGBACK(void) = 1; +} = 2; + +.ft I +/* +* Original version +*/ +.ft CW +version PING_VERS_ORIG { + void + PINGPROC_NULL(void) = 0; + } = 1; +} = 1; + +const PING_VERS = 2; /* \fIlatest version \fP*/ +.vs +.DE +.KE +.LP +The first version described is +.I PING_VERS_PINGBACK +with two procedures, +.I PINGPROC_NULL +and +.I PINGPROC_PINGBACK . +.I PINGPROC_NULL +takes no arguments and returns no results, but it is useful for +computing round-trip times from the client to the server and back +again. By convention, procedure 0 of any RPC protocol should have +the same semantics, and never require any kind of authentication. +The second procedure is used for the client to have the server do a +reverse ping operation back to the client, and it returns the amount +of time (in microseconds) that the operation used. The next version, +.I PING_VERS_ORIG , +is the original version of the protocol +and it does not contain +.I PINGPROC_PINGBACK +procedure. It is useful +for compatibility with old client programs, and as this program +matures it may be dropped from the protocol entirely. +.KS +.NH 2 +\&The RPC Language Specification +.LP +The RPC language is identical to the XDR language, except for the +added definition of a +.I program-def +described below. +.DS +.ft CW +program-def: + "program" identifier "{" + version-def + version-def * + "}" "=" constant ";" + +version-def: + "version" identifier "{" + procedure-def + procedure-def * + "}" "=" constant ";" + +procedure-def: + type-specifier identifier "(" type-specifier ")" + "=" constant ";" +.DE +.KE +.NH 2 +\&Syntax Notes +.IP 1. +The following keywords are added and cannot be used as +identifiers: "program" and "version"; +.IP 2. +A version name cannot occur more than once within the scope of +a program definition. Nor can a version number occur more than once +within the scope of a program definition. +.IP 3. +A procedure name cannot occur more than once within the scope +of a version definition. Nor can a procedure number occur more than +once within the scope of version definition. +.IP 4. +Program identifiers are in the same name space as constant and +type identifiers. +.IP 5. +Only unsigned constants can be assigned to programs, versions +and procedures. +.NH 1 +\&Port Mapper Program Protocol +.LP +The port mapper program maps RPC program and version numbers to +transport-specific port numbers. This program makes dynamic binding +of remote programs possible. +.LP +This is desirable because the range of reserved port numbers is very +small and the number of potential remote programs is very large. By +running only the port mapper on a reserved port, the port numbers of +other remote programs can be ascertained by querying the port mapper. +.LP +The port mapper also aids in broadcast RPC. A given RPC program will +usually have different port number bindings on different machines, so +there is no way to directly broadcast to all of these programs. The +port mapper, however, does have a fixed port number. So, to +broadcast to a given program, the client actually sends its message +to the port mapper located at the broadcast address. Each port +mapper that picks up the broadcast then calls the local service +specified by the client. When the port mapper gets the reply from +the local service, it sends the reply on back to the client. +.KS +.NH 2 +\&Port Mapper Protocol Specification (in RPC Language) +.ie t .DS +.el .DS L +.ft CW +.vs 11 +const PMAP_PORT = 111; /* \fIportmapper port number \fP*/ + +.ft I +/* +* A mapping of (program, version, protocol) to port number +*/ +.ft CW +struct mapping { + unsigned int prog; + unsigned int vers; + unsigned int prot; + unsigned int port; +}; + +.ft I +/* +* Supported values for the "prot" field +*/ +.ft CW +const IPPROTO_TCP = 6; /* \fIprotocol number for TCP/IP \fP*/ +const IPPROTO_UDP = 17; /* \fIprotocol number for UDP/IP \fP*/ + +.ft I +/* +* A list of mappings +*/ +.ft CW +struct *pmaplist { + mapping map; + pmaplist next; +}; +.vs +.DE +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* +* Arguments to callit +*/ +.ft CW +struct call_args { + unsigned int prog; + unsigned int vers; + unsigned int proc; + opaque args<>; +}; + +.ft I +/* +* Results of callit +*/ +.ft CW +struct call_result { + unsigned int port; + opaque res<>; +}; +.vs +.DE +.KE +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* +* Port mapper procedures +*/ +.ft CW +program PMAP_PROG { + version PMAP_VERS { + void + PMAPPROC_NULL(void) = 0; + + bool + PMAPPROC_SET(mapping) = 1; + + bool + PMAPPROC_UNSET(mapping) = 2; + + unsigned int + PMAPPROC_GETPORT(mapping) = 3; + + pmaplist + PMAPPROC_DUMP(void) = 4; + + call_result + PMAPPROC_CALLIT(call_args) = 5; + } = 2; +} = 100000; +.vs +.DE +.NH 2 +\&Port Mapper Operation +.LP +The portmapper program currently supports two protocols (UDP/IP and +TCP/IP). The portmapper is contacted by talking to it on assigned +port number 111 (SUNRPC [8]) on either of these protocols. The +following is a description of each of the portmapper procedures: +.IP \fBPMAPPROC_NULL:\fP +This procedure does no work. By convention, procedure zero of any +protocol takes no parameters and returns no results. +.IP \fBPMAPPROC_SET:\fP +When a program first becomes available on a machine, it registers +itself with the port mapper program on the same machine. The program +passes its program number "prog", version number "vers", transport +protocol number "prot", and the port "port" on which it awaits +service request. The procedure returns a boolean response whose +value is +.I TRUE +if the procedure successfully established the mapping and +.I FALSE +otherwise. The procedure refuses to establish +a mapping if one already exists for the tuple "(prog, vers, prot)". +.IP \fBPMAPPROC_UNSET:\fP +When a program becomes unavailable, it should unregister itself with +the port mapper program on the same machine. The parameters and +results have meanings identical to those of +.I PMAPPROC_SET . +The protocol and port number fields of the argument are ignored. +.IP \fBPMAPPROC_GETPORT:\fP +Given a program number "prog", version number "vers", and transport +protocol number "prot", this procedure returns the port number on +which the program is awaiting call requests. A port value of zeros +means the program has not been registered. The "port" field of the +argument is ignored. +.IP \fBPMAPPROC_DUMP:\fP +This procedure enumerates all entries in the port mapper's database. +The procedure takes no parameters and returns a list of program, +version, protocol, and port values. +.IP \fBPMAPPROC_CALLIT:\fP +This procedure allows a caller to call another remote procedure on +the same machine without knowing the remote procedure's port number. +It is intended for supporting broadcasts to arbitrary remote programs +via the well-known port mapper's port. The parameters "prog", +"vers", "proc", and the bytes of "args" are the program number, +version number, procedure number, and parameters of the remote +procedure. +.LP +.B Note: +.RS +.IP 1. +This procedure only sends a response if the procedure was +successfully executed and is silent (no response) otherwise. +.IP 2. +The port mapper communicates with the remote program using UDP/IP +only. +.RE +.LP +The procedure returns the remote program's port number, and the bytes +of results are the results of the remote procedure. +.bp +.NH 1 +\&References +.LP +[1] Birrell, Andrew D. & Nelson, Bruce Jay; "Implementing Remote +Procedure Calls"; XEROX CSL-83-7, October 1983. +.LP +[2] Cheriton, D.; "VMTP: Versatile Message Transaction Protocol", +Preliminary Version 0.3; Stanford University, January 1987. +.LP +[3] Diffie & Hellman; "New Directions in Cryptography"; IEEE +Transactions on Information Theory IT-22, November 1976. +.LP +[4] Harrenstien, K.; "Time Server", RFC 738; Information Sciences +Institute, October 1977. +.LP +[5] National Bureau of Standards; "Data Encryption Standard"; Federal +Information Processing Standards Publication 46, January 1977. +.LP +[6] Postel, J.; "Transmission Control Protocol - DARPA Internet +Program Protocol Specification", RFC 793; Information Sciences +Institute, September 1981. +.LP +[7] Postel, J.; "User Datagram Protocol", RFC 768; Information Sciences +Institute, August 1980. +.LP +[8] Reynolds, J. & Postel, J.; "Assigned Numbers", RFC 923; Information +Sciences Institute, October 1984. diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/rpcgen.ms b/c/src/exec/librpc/src/rpc/PSD.doc/rpcgen.ms index e69de29bb2..b4e50e5d6f 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/rpcgen.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/rpcgen.ms @@ -0,0 +1,1299 @@ +.\" +.\" Must use -- tbl -- for this one +.\" +.\" @(#)rpcgen.ms 2.2 88/08/04 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH '\fBrpcgen\fP Programming Guide''Page %' +.EH 'Page %''\fBrpcgen\fP Programming Guide' +.if \\n%=1 .bp +.SH +\&\fBrpcgen\fP Programming Guide +.NH 0 +\&The \fBrpcgen\fP Protocol Compiler +.IX rpcgen "" \fIrpcgen\fP "" PAGE MAJOR +.LP +.IX RPC "" "" \fIrpcgen\fP +The details of programming applications to use Remote Procedure Calls +can be overwhelming. Perhaps most daunting is the writing of the XDR +routines necessary to convert procedure arguments and results into +their network format and vice-versa. +.LP +Fortunately, +.I rpcgen(1) +exists to help programmers write RPC applications simply and directly. +.I rpcgen +does most of the dirty work, allowing programmers to debug +the main features of their application, instead of requiring them to +spend most of their time debugging their network interface code. +.LP +.I rpcgen +is a compiler. It accepts a remote program interface definition written +in a language, called RPC Language, which is similar to C. It produces a C +language output which includes stub versions of the client routines, a +server skeleton, XDR filter routines for both parameters and results, and a +header file that contains common definitions. The client stubs interface +with the RPC library and effectively hide the network from their callers. +The server stub similarly hides the network from the server procedures that +are to be invoked by remote clients. +.I rpcgen 's +output files can be compiled and linked in the usual way. The developer +writes server procedures\(emin any language that observes Sun calling +conventions\(emand links them with the server skeleton produced by +.I rpcgen +to get an executable server program. To use a remote program, a programmer +writes an ordinary main program that makes local procedure calls to the +client stubs produced by +.I rpcgen . +Linking this program with +.I rpcgen 's +stubs creates an executable program. (At present the main program must be +written in C). +.I rpcgen +options can be used to suppress stub generation and to specify the transport +to be used by the server stub. +.LP +Like all compilers, +.I rpcgen +reduces development time +that would otherwise be spent coding and debugging low-level routines. +All compilers, including +.I rpcgen , +do this at a small cost in efficiency +and flexibility. However, many compilers allow escape hatches for +programmers to mix low-level code with high-level code. +.I rpcgen +is no exception. In speed-critical applications, hand-written routines +can be linked with the +.I rpcgen +output without any difficulty. Also, one may proceed by using +.I rpcgen +output as a starting point, and then rewriting it as necessary. +(If you need a discussion of RPC programming without +.I rpcgen , +see the +.I "Remote Procedure Call Programming Guide)\. +.NH 1 +\&Converting Local Procedures into Remote Procedures +.IX rpcgen "local procedures" \fIrpcgen\fP +.IX rpcgen "remote procedures" \fIrpcgen\fP +.LP +Assume an application that runs on a single machine, one which we want +to convert to run over the network. Here we will demonstrate such a +conversion by way of a simple example\(ema program that prints a +message to the console: +.ie t .DS +.el .DS L +.ft I +/* + * printmsg.c: print a message on the console + */ +.ft CW +#include + +main(argc, argv) + int argc; + char *argv[]; +{ + char *message; + + if (argc < 2) { + fprintf(stderr, "usage: %s \en", argv[0]); + exit(1); + } + message = argv[1]; + + if (!printmessage(message)) { + fprintf(stderr, "%s: couldn't print your message\en", + argv[0]); + exit(1); + } + printf("Message Delivered!\en"); + exit(0); +} +.ft I +/* + * Print a message to the console. + * Return a boolean indicating whether the message was actually printed. + */ +.ft CW +printmessage(msg) + char *msg; +{ + FILE *f; + + f = fopen("/dev/console", "w"); + if (f == NULL) { + return (0); + } + fprintf(f, "%s\en", msg); + fclose(f); + return(1); +} +.DE +.LP +And then, of course: +.ie t .DS +.el .DS L +.ft CW +example% \fBcc printmsg.c -o printmsg\fP +example% \fBprintmsg "Hello, there."\fP +Message delivered! +example% +.DE +.LP +If +.I printmessage() +was turned into a remote procedure, +then it could be called from anywhere in the network. +Ideally, one would just like to stick a keyword like +.I remote +in front of a +procedure to turn it into a remote procedure. Unfortunately, +we have to live within the constraints of the C language, since +it existed long before RPC did. But even without language +support, it's not very difficult to make a procedure remote. +.LP +In general, it's necessary to figure out what the types are for +all procedure inputs and outputs. In this case, we have a +procedure +.I printmessage() +which takes a string as input, and returns an integer +as output. Knowing this, we can write a protocol specification in RPC +language that describes the remote version of +.I printmessage (). +Here it is: +.ie t .DS +.el .DS L +.ft I +/* + * msg.x: Remote message printing protocol + */ +.ft CW + +program MESSAGEPROG { + version MESSAGEVERS { + int PRINTMESSAGE(string) = 1; + } = 1; +} = 99; +.DE +.LP +Remote procedures are part of remote programs, so we actually declared +an entire remote program here which contains the single procedure +.I PRINTMESSAGE . +This procedure was declared to be in version 1 of the +remote program. No null procedure (procedure 0) is necessary because +.I rpcgen +generates it automatically. +.LP +Notice that everything is declared with all capital letters. This is +not required, but is a good convention to follow. +.LP +Notice also that the argument type is \*Qstring\*U and not \*Qchar *\*U. This +is because a \*Qchar *\*U in C is ambiguous. Programmers usually intend it +to mean a null-terminated string of characters, but it could also +represent a pointer to a single character or a pointer to an array of +characters. In RPC language, a null-terminated string is +unambiguously called a \*Qstring\*U. +.LP +There are just two more things to write. First, there is the remote +procedure itself. Here's the definition of a remote procedure +to implement the +.I PRINTMESSAGE +procedure we declared above: +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * msg_proc.c: implementation of the remote procedure "printmessage" + */ +.ft CW + +#include +#include /* \fIalways needed\fP */ +#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */ + +.ft I +/* + * Remote verson of "printmessage" + */ +.ft CW +int * +printmessage_1(msg) + char **msg; +{ + static int result; /* \fImust be static!\fP */ + FILE *f; + + f = fopen("/dev/console", "w"); + if (f == NULL) { + result = 0; + return (&result); + } + fprintf(f, "%s\en", *msg); + fclose(f); + result = 1; + return (&result); +} +.vs +.DE +.LP +Notice here that the declaration of the remote procedure +.I printmessage_1() +differs from that of the local procedure +.I printmessage() +in three ways: +.IP 1. +It takes a pointer to a string instead of a string itself. This +is true of all remote procedures: they always take pointers to their +arguments rather than the arguments themselves. +.IP 2. +It returns a pointer to an integer instead of an integer itself. This is +also generally true of remote procedures: they always return a pointer +to their results. +.IP 3. +It has an \*Q_1\*U appended to its name. In general, all remote +procedures called by +.I rpcgen +are named by the following rule: the name in the program definition +(here +.I PRINTMESSAGE ) +is converted to all +lower-case letters, an underbar (\*Q_\*U) is appended to it, and +finally the version number (here 1) is appended. +.LP +The last thing to do is declare the main client program that will call +the remote procedure. Here it is: +.ie t .DS +.el .DS L +.ft I +/* + * rprintmsg.c: remote version of "printmsg.c" + */ +.ft CW +#include +#include /* \fIalways needed\fP */ +#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */ + +main(argc, argv) + int argc; + char *argv[]; +{ + CLIENT *cl; + int *result; + char *server; + char *message; + + if (argc < 3) { + fprintf(stderr, "usage: %s host message\en", argv[0]); + exit(1); + } + +.ft I + /* + * Save values of command line arguments + */ +.ft CW + server = argv[1]; + message = argv[2]; + +.ft I + /* + * Create client "handle" used for calling \fIMESSAGEPROG\fP on the + * server designated on the command line. We tell the RPC package + * to use the "tcp" protocol when contacting the server. + */ +.ft CW + cl = clnt_create(server, MESSAGEPROG, MESSAGEVERS, "tcp"); + if (cl == NULL) { +.ft I + /* + * Couldn't establish connection with server. + * Print error message and die. + */ +.ft CW + clnt_pcreateerror(server); + exit(1); + } + +.ft I + /* + * Call the remote procedure "printmessage" on the server + */ +.ft CW + result = printmessage_1(&message, cl); + if (result == NULL) { +.ft I + /* + * An error occurred while calling the server. + * Print error message and die. + */ +.ft CW + clnt_perror(cl, server); + exit(1); + } + +.ft I + /* + * Okay, we successfully called the remote procedure. + */ +.ft CW + if (*result == 0) { +.ft I + /* + * Server was unable to print our message. + * Print error message and die. + */ +.ft CW + fprintf(stderr, "%s: %s couldn't print your message\en", + argv[0], server); + exit(1); + } + +.ft I + /* + * The message got printed on the server's console + */ +.ft CW + printf("Message delivered to %s!\en", server); +} +.DE +There are two things to note here: +.IP 1. +.IX "client handle, used by rpcgen" "" "client handle, used by \fIrpcgen\fP" +First a client \*Qhandle\*U is created using the RPC library routine +.I clnt_create (). +This client handle will be passed to the stub routines +which call the remote procedure. +.IP 2. +The remote procedure +.I printmessage_1() +is called exactly the same way as it is declared in +.I msg_proc.c +except for the inserted client handle as the first argument. +.LP +Here's how to put all of the pieces together: +.ie t .DS +.el .DS L +.ft CW +example% \fBrpcgen msg.x\fP +example% \fBcc rprintmsg.c msg_clnt.c -o rprintmsg\fP +example% \fBcc msg_proc.c msg_svc.c -o msg_server\fP +.DE +Two programs were compiled here: the client program +.I rprintmsg +and the server program +.I msg_server . +Before doing this though, +.I rpcgen +was used to fill in the missing pieces. +.LP +Here is what +.I rpcgen +did with the input file +.I msg.x : +.IP 1. +It created a header file called +.I msg.h +that contained +.I #define 's +for +.I MESSAGEPROG , +.I MESSAGEVERS +and +.I PRINTMESSAGE +for use in the other modules. +.IP 2. +It created client \*Qstub\*U routines in the +.I msg_clnt.c +file. In this case there is only one, the +.I printmessage_1() +that was referred to from the +.I printmsg +client program. The name of the output file for +client stub routines is always formed in this way: if the name of the +input file is +.I FOO.x , +the client stubs output file is called +.I FOO_clnt.c . +.IP 3. +It created the server program which calls +.I printmessage_1() +in +.I msg_proc.c . +This server program is named +.I msg_svc.c . +The rule for naming the server output file is similar to the +previous one: for an input file called +.I FOO.x , +the output server file is named +.I FOO_svc.c . +.LP +Now we're ready to have some fun. First, copy the server to a +remote machine and run it. For this example, the +machine is called \*Qmoon\*U. Server processes are run in the +background, because they never exit. +.ie t .DS +.el .DS L +.ft CW +moon% \fBmsg_server &\fP +.DE +Then on our local machine (\*Qsun\*U) we can print a message on \*Qmoon\*Us +console. +.ie t .DS +.el .DS L +.ft CW +sun% \fBprintmsg moon "Hello, moon."\fP +.DE +The message will get printed to \*Qmoon\*Us console. You can print a +message on anybody's console (including your own) with this program if +you are able to copy the server to their machine and run it. +.NH 1 +\&Generating XDR Routines +.IX RPC "generating XDR routines" +.LP +The previous example only demonstrated the automatic generation of +client and server RPC code. +.I rpcgen +may also be used to generate XDR routines, that is, the routines +necessary to convert local data +structures into network format and vice-versa. This example presents +a complete RPC service\(ema remote directory listing service, which uses +.I rpcgen +not only to generate stub routines, but also to generate the XDR +routines. Here is the protocol description file: +.ie t .DS +.el .DS L +.ft I +/* + * dir.x: Remote directory listing protocol + */ +.ft CW +const MAXNAMELEN = 255; /* \fImaximum length of a directory entry\fP */ + +typedef string nametype; /* \fIa directory entry\fP */ + +typedef struct namenode *namelist; /* \fIa link in the listing\fP */ + +.ft I +/* + * A node in the directory listing + */ +.ft CW +struct namenode { + nametype name; /* \fIname of directory entry\fP */ + namelist next; /* \fInext entry\fP */ +}; + +.ft I +/* + * The result of a READDIR operation. + */ +.ft CW +union readdir_res switch (int errno) { +case 0: + namelist list; /* \fIno error: return directory listing\fP */ +default: + void; /* \fIerror occurred: nothing else to return\fP */ +}; + +.ft I +/* + * The directory program definition + */ +.ft CW +program DIRPROG { + version DIRVERS { + readdir_res + READDIR(nametype) = 1; + } = 1; +} = 76; +.DE +.SH +Note: +.I +Types (like +.I readdir_res +in the example above) can be defined using +the \*Qstruct\*U, \*Qunion\*U and \*Qenum\*U keywords, but those keywords +should not be used in subsequent declarations of variables of those types. +For example, if you define a union \*Qfoo\*U, you should declare using +only \*Qfoo\*U and not \*Qunion foo\*U. In fact, +.I rpcgen +compiles +RPC unions into C structures and it is an error to declare them using the +\*Qunion\*U keyword. +.LP +Running +.I rpcgen +on +.I dir.x +creates four output files. Three are the same as before: header file, +client stub routines and server skeleton. The fourth are the XDR routines +necessary for converting the data types we declared into XDR format and +vice-versa. These are output in the file +.I dir_xdr.c . +.LP +Here is the implementation of the +.I READDIR +procedure. +.ie t .DS +.el .DS L +.vs 11 +.ft I +/* + * dir_proc.c: remote readdir implementation + */ +.ft CW +#include +#include +#include "dir.h" + +extern int errno; +extern char *malloc(); +extern char *strdup(); + +readdir_res * +readdir_1(dirname) + nametype *dirname; +{ + DIR *dirp; + struct direct *d; + namelist nl; + namelist *nlp; + static readdir_res res; /* \fImust be static\fP! */ + +.ft I + /* + * Open directory + */ +.ft CW + dirp = opendir(*dirname); + if (dirp == NULL) { + res.errno = errno; + return (&res); + } + +.ft I + /* + * Free previous result + */ +.ft CW + xdr_free(xdr_readdir_res, &res); + +.ft I + /* + * Collect directory entries. + * Memory allocated here will be freed by \fIxdr_free\fP + * next time \fIreaddir_1\fP is called + */ +.ft CW + nlp = &res.readdir_res_u.list; + while (d = readdir(dirp)) { + nl = *nlp = (namenode *) malloc(sizeof(namenode)); + nl->name = strdup(d->d_name); + nlp = &nl->next; + } + *nlp = NULL; + +.ft I + /* + * Return the result + */ +.ft CW + res.errno = 0; + closedir(dirp); + return (&res); +} +.vs +.DE +Finally, there is the client side program to call the server: +.ie t .DS +.el .DS L +.ft I +/* + * rls.c: Remote directory listing client + */ +.ft CW +#include +#include /* \fIalways need this\fP */ +#include "dir.h" /* \fIwill be generated by rpcgen\fI */ + +extern int errno; + +main(argc, argv) + int argc; + char *argv[]; +{ + CLIENT *cl; + char *server; + char *dir; + readdir_res *result; + namelist nl; + + + if (argc != 3) { + fprintf(stderr, "usage: %s host directory\en", + argv[0]); + exit(1); + } + +.ft I + /* + * Remember what our command line arguments refer to + */ +.ft CW + server = argv[1]; + dir = argv[2]; + +.ft I + /* + * Create client "handle" used for calling \fIMESSAGEPROG\fP on the + * server designated on the command line. We tell the RPC package + * to use the "tcp" protocol when contacting the server. + */ +.ft CW + cl = clnt_create(server, DIRPROG, DIRVERS, "tcp"); + if (cl == NULL) { +.ft I + /* + * Couldn't establish connection with server. + * Print error message and die. + */ +.ft CW + clnt_pcreateerror(server); + exit(1); + } + +.ft I + /* + * Call the remote procedure \fIreaddir\fP on the server + */ +.ft CW + result = readdir_1(&dir, cl); + if (result == NULL) { +.ft I + /* + * An error occurred while calling the server. + * Print error message and die. + */ +.ft CW + clnt_perror(cl, server); + exit(1); + } + +.ft I + /* + * Okay, we successfully called the remote procedure. + */ +.ft CW + if (result->errno != 0) { +.ft I + /* + * A remote system error occurred. + * Print error message and die. + */ +.ft CW + errno = result->errno; + perror(dir); + exit(1); + } + +.ft I + /* + * Successfully got a directory listing. + * Print it out. + */ +.ft CW + for (nl = result->readdir_res_u.list; nl != NULL; + nl = nl->next) { + printf("%s\en", nl->name); + } + exit(0); +} +.DE +Compile everything, and run. +.DS +.ft CW +sun% \fBrpcgen dir.x\fP +sun% \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fP +sun% \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fP + +sun% \fBdir_svc &\fP + +moon% \fBrls sun /usr/pub\fP +\&. +\&.. +ascii +eqnchar +greek +kbd +marg8 +tabclr +tabs +tabs4 +moon% +.DE +.LP +.IX "debugging with rpcgen" "" "debugging with \fIrpcgen\fP" +A final note about +.I rpcgen : +The client program and the server procedure can be tested together +as a single program by simply linking them with each other rather +than with the client and server stubs. The procedure calls will be +executed as ordinary local procedure calls and the program can be +debugged with a local debugger such as +.I dbx . +When the program is working, the client program can be linked to +the client stub produced by +.I rpcgen +and the server procedures can be linked to the server stub produced +by +.I rpcgen . +.SH +.I NOTE : +\fIIf you do this, you may want to comment out calls to RPC library +routines, and have client-side routines call server routines +directly.\fP +.LP +.NH 1 +\&The C-Preprocessor +.IX rpcgen "C-preprocessor" \fIrpcgen\fP +.LP +The C-preprocessor is run on all input files before they are +compiled, so all the preprocessor directives are legal within a \*Q.x\*U +file. Four symbols may be defined, depending upon which output file is +getting generated. The symbols are: +.TS +box tab (&); +lfI lfI +lfL l . +Symbol&Usage +_ +RPC_HDR&for header-file output +RPC_XDR&for XDR routine output +RPC_SVC&for server-skeleton output +RPC_CLNT&for client stub output +.TE +.LP +Also, +.I rpcgen +does a little preprocessing of its own. Any line that +begins with a percent sign is passed directly into the output file, +without any interpretation of the line. Here is a simple example that +demonstrates the preprocessing features. +.ie t .DS +.el .DS L +.ft I +/* + * time.x: Remote time protocol + */ +.ft CW +program TIMEPROG { + version TIMEVERS { + unsigned int TIMEGET(void) = 1; + } = 1; +} = 44; + +#ifdef RPC_SVC +%int * +%timeget_1() +%{ +% static int thetime; +% +% thetime = time(0); +% return (&thetime); +%} +#endif +.DE +The '%' feature is not generally recommended, as there is no guarantee +that the compiler will stick the output where you intended. +.NH 1 +\&\fBrpcgen\fP Programming Notes +.IX rpcgen "other operations" \fIrpcgen\fP +.sp +.NH 2 +\&Timeout Changes +.IX rpcgen "timeout changes" \fIrpcgen\fP +.LP +RPC sets a default timeout of 25 seconds for RPC calls when +.I clnt_create() +is used. This timeout may be changed using +.I clnt_control() +Here is a small code fragment to demonstrate use of +.I clnt_control (): +.ID +struct timeval tv; +CLIENT *cl; +.sp .5 +cl = clnt_create("somehost", SOMEPROG, SOMEVERS, "tcp"); +if (cl == NULL) { + exit(1); +} +tv.tv_sec = 60; /* \fIchange timeout to 1 minute\fP */ +tv.tv_usec = 0; +clnt_control(cl, CLSET_TIMEOUT, &tv); +.DE +.NH 2 +\&Handling Broadcast on the Server Side +.IX "broadcast RPC" +.IX rpcgen "broadcast RPC" \fIrpcgen\fP +.LP +When a procedure is known to be called via broadcast RPC, +it is usually wise for the server to not reply unless it can provide +some useful information to the client. This prevents the network +from getting flooded by useless replies. +.LP +To prevent the server from replying, a remote procedure can +return NULL as its result, and the server code generated by +.I rpcgen +will detect this and not send out a reply. +.LP +Here is an example of a procedure that replies only if it +thinks it is an NFS server: +.ID +void * +reply_if_nfsserver() +{ + char notnull; /* \fIjust here so we can use its address\fP */ +.sp .5 + if (access("/etc/exports", F_OK) < 0) { + return (NULL); /* \fIprevent RPC from replying\fP */ + } +.ft I + /* + * return non-null pointer so RPC will send out a reply + */ +.ft L + return ((void *)¬null); +} +.DE +Note that if procedure returns type \*Qvoid *\*U, they must return a non-NULL +pointer if they want RPC to reply for them. +.NH 2 +\&Other Information Passed to Server Procedures +.LP +Server procedures will often want to know more about an RPC call +than just its arguments. For example, getting authentication information +is important to procedures that want to implement some level of security. +This extra information is actually supplied to the server procedure as a +second argument. Here is an example to demonstrate its use. What we've +done here is rewrite the previous +.I printmessage_1() +procedure to only allow root users to print a message to the console. +.ID +int * +printmessage_1(msg, rq) + char **msg; + struct svc_req *rq; +{ + static in result; /* \fIMust be static\fP */ + FILE *f; + struct suthunix_parms *aup; +.sp .5 + aup = (struct authunix_parms *)rq->rq_clntcred; + if (aup->aup_uid != 0) { + result = 0; + return (&result); + } +.sp +.ft I + /* + * Same code as before. + */ +.ft L +} +.DE +.NH 1 +\&RPC Language +.IX RPCL +.IX rpcgen "RPC Language" \fIrpcgen\fP +.LP +RPC language is an extension of XDR language. The sole extension is +the addition of the +.I program +type. For a complete description of the XDR language syntax, see the +.I "External Data Representation Standard: Protocol Specification" +chapter. For a description of the RPC extensions to the XDR language, +see the +.I "Remote Procedure Calls: Protocol Specification" +chapter. +.LP +However, XDR language is so close to C that if you know C, you know most +of it already. We describe here the syntax of the RPC language, +showing a few examples along the way. We also show how the various +RPC and XDR type definitions get compiled into C type definitions in +the output header file. +.KS +.NH 2 +Definitions +\& +.IX rpcgen definitions \fIrpcgen\fP +.LP +An RPC language file consists of a series of definitions. +.DS L +.ft CW + definition-list: + definition ";" + definition ";" definition-list +.DE +.KE +It recognizes five types of definitions. +.DS L +.ft CW + definition: + enum-definition + struct-definition + union-definition + typedef-definition + const-definition + program-definition +.DE +.NH 2 +Structures +\& +.IX rpcgen structures \fIrpcgen\fP +.LP +An XDR struct is declared almost exactly like its C counterpart. It +looks like the following: +.DS L +.ft CW + struct-definition: + "struct" struct-ident "{" + declaration-list + "}" + + declaration-list: + declaration ";" + declaration ";" declaration-list +.DE +As an example, here is an XDR structure to a two-dimensional +coordinate, and the C structure that it gets compiled into in the +output header file. +.DS +.ft CW + struct coord { struct coord { + int x; --> int x; + int y; int y; + }; }; + typedef struct coord coord; +.DE +The output is identical to the input, except for the added +.I typedef +at the end of the output. This allows one to use \*Qcoord\*U instead of +\*Qstruct coord\*U when declaring items. +.NH 2 +Unions +\& +.IX rpcgen unions \fIrpcgen\fP +.LP +XDR unions are discriminated unions, and look quite different from C +unions. They are more analogous to Pascal variant records than they +are to C unions. +.DS L +.ft CW + union-definition: + "union" union-ident "switch" "(" declaration ")" "{" + case-list + "}" + + case-list: + "case" value ":" declaration ";" + "default" ":" declaration ";" + "case" value ":" declaration ";" case-list +.DE +Here is an example of a type that might be returned as the result of a +\*Qread data\*U operation. If there is no error, return a block of data. +Otherwise, don't return anything. +.DS L +.ft CW + union read_result switch (int errno) { + case 0: + opaque data[1024]; + default: + void; + }; +.DE +It gets compiled into the following: +.DS L +.ft CW + struct read_result { + int errno; + union { + char data[1024]; + } read_result_u; + }; + typedef struct read_result read_result; +.DE +Notice that the union component of the output struct has the name as +the type name, except for the trailing \*Q_u\*U. +.NH 2 +Enumerations +\& +.IX rpcgen enumerations \fIrpcgen\fP +.LP +XDR enumerations have the same syntax as C enumerations. +.DS L +.ft CW + enum-definition: + "enum" enum-ident "{" + enum-value-list + "}" + + enum-value-list: + enum-value + enum-value "," enum-value-list + + enum-value: + enum-value-ident + enum-value-ident "=" value +.DE +Here is a short example of an XDR enum, and the C enum that it gets +compiled into. +.DS L +.ft CW + enum colortype { enum colortype { + RED = 0, RED = 0, + GREEN = 1, --> GREEN = 1, + BLUE = 2 BLUE = 2, + }; }; + typedef enum colortype colortype; +.DE +.NH 2 +Typedef +\& +.IX rpcgen typedef \fIrpcgen\fP +.LP +XDR typedefs have the same syntax as C typedefs. +.DS L +.ft CW + typedef-definition: + "typedef" declaration +.DE +Here is an example that defines a +.I fname_type +used for declaring +file name strings that have a maximum length of 255 characters. +.DS L +.ft CW +typedef string fname_type<255>; --> typedef char *fname_type; +.DE +.NH 2 +Constants +\& +.IX rpcgen constants \fIrpcgen\fP +.LP +XDR constants symbolic constants that may be used wherever a +integer constant is used, for example, in array size specifications. +.DS L +.ft CW + const-definition: + "const" const-ident "=" integer +.DE +For example, the following defines a constant +.I DOZEN +equal to 12. +.DS L +.ft CW + const DOZEN = 12; --> #define DOZEN 12 +.DE +.NH 2 +Programs +\& +.IX rpcgen programs \fIrpcgen\fP +.LP +RPC programs are declared using the following syntax: +.DS L +.ft CW + program-definition: + "program" program-ident "{" + version-list + "}" "=" value + + version-list: + version ";" + version ";" version-list + + version: + "version" version-ident "{" + procedure-list + "}" "=" value + + procedure-list: + procedure ";" + procedure ";" procedure-list + + procedure: + type-ident procedure-ident "(" type-ident ")" "=" value +.DE +For example, here is the time protocol, revisited: +.ie t .DS +.el .DS L +.ft I +/* + * time.x: Get or set the time. Time is represented as number of seconds + * since 0:00, January 1, 1970. + */ +.ft CW +program TIMEPROG { + version TIMEVERS { + unsigned int TIMEGET(void) = 1; + void TIMESET(unsigned) = 2; + } = 1; +} = 44; +.DE +This file compiles into #defines in the output header file: +.ie t .DS +.el .DS L +.ft CW +#define TIMEPROG 44 +#define TIMEVERS 1 +#define TIMEGET 1 +#define TIMESET 2 +.DE +.NH 2 +Declarations +\& +.IX rpcgen declarations \fIrpcgen\fP +.LP +In XDR, there are only four kinds of declarations. +.DS L +.ft CW + declaration: + simple-declaration + fixed-array-declaration + variable-array-declaration + pointer-declaration +.DE +\fB1) Simple declarations\fP are just like simple C declarations. +.DS L +.ft CW + simple-declaration: + type-ident variable-ident +.DE +Example: +.DS L +.ft CW + colortype color; --> colortype color; +.DE +\fB2) Fixed-length Array Declarations\fP are just like C array declarations: +.DS L +.ft CW + fixed-array-declaration: + type-ident variable-ident "[" value "]" +.DE +Example: +.DS L +.ft CW + colortype palette[8]; --> colortype palette[8]; +.DE +\fB3) Variable-Length Array Declarations\fP have no explicit syntax +in C, so XDR invents its own using angle-brackets. +.DS L +.ft CW +variable-array-declaration: + type-ident variable-ident "<" value ">" + type-ident variable-ident "<" ">" +.DE +The maximum size is specified between the angle brackets. The size may +be omitted, indicating that the array may be of any size. +.DS L +.ft CW + int heights<12>; /* \fIat most 12 items\fP */ + int widths<>; /* \fIany number of items\fP */ +.DE +Since variable-length arrays have no explicit syntax in C, these +declarations are actually compiled into \*Qstruct\*Us. For example, the +\*Qheights\*U declaration gets compiled into the following struct: +.DS L +.ft CW + struct { + u_int heights_len; /* \fI# of items in array\fP */ + int *heights_val; /* \fIpointer to array\fP */ + } heights; +.DE +Note that the number of items in the array is stored in the \*Q_len\*U +component and the pointer to the array is stored in the \*Q_val\*U +component. The first part of each of these component's names is the +same as the name of the declared XDR variable. +.LP +\fB4) Pointer Declarations\fP are made in +XDR exactly as they are in C. You can't +really send pointers over the network, but you can use XDR pointers +for sending recursive data types such as lists and trees. The type is +actually called \*Qoptional-data\*U, not \*Qpointer\*U, in XDR language. +.DS L +.ft CW + pointer-declaration: + type-ident "*" variable-ident +.DE +Example: +.DS L +.ft CW + listitem *next; --> listitem *next; +.DE +.NH 2 +\&Special Cases +.IX rpcgen "special cases" \fIrpcgen\fP +.LP +There are a few exceptions to the rules described above. +.LP +.B Booleans: +C has no built-in boolean type. However, the RPC library does a +boolean type called +.I bool_t +that is either +.I TRUE +or +.I FALSE . +Things declared as type +.I bool +in XDR language are compiled into +.I bool_t +in the output header file. +.LP +Example: +.DS L +.ft CW + bool married; --> bool_t married; +.DE +.B Strings: +C has no built-in string type, but instead uses the null-terminated +\*Qchar *\*U convention. In XDR language, strings are declared using the +\*Qstring\*U keyword, and compiled into \*Qchar *\*Us in the output header +file. The maximum size contained in the angle brackets specifies the +maximum number of characters allowed in the strings (not counting the +.I NULL +character). The maximum size may be left off, indicating a string +of arbitrary length. +.LP +Examples: +.DS L +.ft CW + string name<32>; --> char *name; + string longname<>; --> char *longname; +.DE +.B "Opaque Data:" +Opaque data is used in RPC and XDR to describe untyped data, that is, +just sequences of arbitrary bytes. It may be declared either as a +fixed or variable length array. +.DS L +Examples: +.ft CW + opaque diskblock[512]; --> char diskblock[512]; + + opaque filedata<1024>; --> struct { + u_int filedata_len; + char *filedata_val; + } filedata; +.DE +.B Voids: +In a void declaration, the variable is not named. The declaration is +just \*Qvoid\*U and nothing else. Void declarations can only occur in two +places: union definitions and program definitions (as the argument or +result of a remote procedure). diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/xdr.nts.ms b/c/src/exec/librpc/src/rpc/PSD.doc/xdr.nts.ms index e69de29bb2..6c2d482dea 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/xdr.nts.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/xdr.nts.ms @@ -0,0 +1,1966 @@ +.\" +.\" Must use -- eqn -- with this one +.\" +.\" @(#)xdr.nts.ms 2.2 88/08/05 4.0 RPCSRC +.EQ +delim $$ +.EN +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'External Data Representation: Sun Technical Notes''Page %' +.EH 'Page %''External Data Representation: Sun Technical Notes' +.if \\n%=1 .bp +.SH +\&External Data Representation: Sun Technical Notes +.IX XDR "Sun technical notes" +.LP +This chapter contains technical notes on Sun's implementation of the +External Data Representation (XDR) standard, a set of library routines +that allow a C programmer to describe arbitrary data structures in a +machinex-independent fashion. +For a formal specification of the XDR +standard, see the +.I "External Data Representation Standard: Protocol Specification". +XDR is the backbone of Sun's Remote Procedure Call package, in the +sense that data for remote procedure calls is transmitted using the +standard. XDR library routines should be used to transmit data +that is accessed (read or written) by more than one type of machine.\** +.FS +.IX XDR "system routines" +For a compete specification of the system External Data Representation +routines, see the +.I xdr(3N) +manual page. +.FE +.LP +This chapter contains a short tutorial overview of the XDR library +routines, a guide to accessing currently available XDR streams, and +information on defining new streams and data types. XDR was designed +to work across different languages, operating systems, and machine +architectures. Most users (particularly RPC users) will only need +the information in the +.I "Number Filters", +.I "Floating Point Filters", +and +.I "Enumeration Filters" +sections. +Programmers wishing to implement RPC and XDR on new machines +will be interested in the rest of the chapter, as well as the +.I "External Data Representaiton Standard: Protocol Specification", +which will be their primary reference. +.SH +Note: +.I +.I rpcgen +can be used to write XDR routines even in cases where no RPC calls are +being made. +.LP +On Sun systems, +C programs that want to use XDR routines +must include the file +.I , +which contains all the necessary interfaces to the XDR system. +Since the C library +.I libc.a +contains all the XDR routines, +compile as normal. +.DS +example% \fBcc\0\fIprogram\fP.c\fI +.DE +.ne 3i +.NH 0 +\&Justification +.IX XDR justification +.LP +Consider the following two programs, +.I writer : +.ie t .DS +.el .DS L +.ft CW +#include +.sp.5 +main() /* \fIwriter.c\fP */ +{ + long i; +.sp.5 + for (i = 0; i < 8; i++) { + if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) { + fprintf(stderr, "failed!\en"); + exit(1); + } + } + exit(0); +} +.DE +and +.I reader : +.ie t .DS +.el .DS L +.ft CW +#include +.sp.5 +main() /* \fIreader.c\fP */ +{ + long i, j; +.sp.5 + for (j = 0; j < 8; j++) { + if (fread((char *)&i, sizeof (i), 1, stdin) != 1) { + fprintf(stderr, "failed!\en"); + exit(1); + } + printf("%ld ", i); + } + printf("\en"); + exit(0); +} +.DE +The two programs appear to be portable, because (a) they pass +.I lint +checking, and (b) they exhibit the same behavior when executed +on two different hardware architectures, a Sun and a VAX. +.LP +Piping the output of the +.I writer +program to the +.I reader +program gives identical results on a Sun or a VAX. +.DS +.ft CW +sun% \fBwriter | reader\fP +0 1 2 3 4 5 6 7 +sun% + + +vax% \fBwriter | reader\fP +0 1 2 3 4 5 6 7 +vax% +.DE +With the advent of local area networks and 4.2BSD came the concept +of \*Qnetwork pipes\*U \(em a process produces data on one machine, +and a second process consumes data on another machine. +A network pipe can be constructed with +.I writer +and +.I reader . +Here are the results if the first produces data on a Sun, +and the second consumes data on a VAX. +.DS +.ft CW +sun% \fBwriter | rsh vax reader\fP +0 16777216 33554432 50331648 67108864 83886080 100663296 +117440512 +sun% +.DE +Identical results can be obtained by executing +.I writer +on the VAX and +.I reader +on the Sun. These results occur because the byte ordering +of long integers differs between the VAX and the Sun, +even though word size is the same. +Note that $16777216$ is $2 sup 24$ \(em +when four bytes are reversed, the 1 winds up in the 24th bit. +.LP +Whenever data is shared by two or more machine types, there is +a need for portable data. Programs can be made data-portable by +replacing the +.I read() +and +.I write() +calls with calls to an XDR library routine +.I xdr_long() , +a filter that knows the standard representation +of a long integer in its external form. +Here are the revised versions of +.I writer : +.ie t .DS +.el .DS L +.ft CW +#include +#include /* \fIxdr is a sub-library of rpc\fP */ +.sp.5 +main() /* \fIwriter.c\fP */ +{ + XDR xdrs; + long i; +.sp.5 + xdrstdio_create(&xdrs, stdout, XDR_ENCODE); + for (i = 0; i < 8; i++) { + if (!xdr_long(&xdrs, &i)) { + fprintf(stderr, "failed!\en"); + exit(1); + } + } + exit(0); +} +.DE +and +.I reader : +.ie t .DS +.el .DS L +.ft CW +#include +#include /* \fIxdr is a sub-library of rpc\fP */ +.sp.5 +main() /* \fIreader.c\fP */ +{ + XDR xdrs; + long i, j; +.sp.5 + xdrstdio_create(&xdrs, stdin, XDR_DECODE); + for (j = 0; j < 8; j++) { + if (!xdr_long(&xdrs, &i)) { + fprintf(stderr, "failed!\en"); + exit(1); + } + printf("%ld ", i); + } + printf("\en"); + exit(0); +} +.DE +The new programs were executed on a Sun, +on a VAX, and from a Sun to a VAX; +the results are shown below. +.DS +.ft CW +sun% \fBwriter | reader\fP +0 1 2 3 4 5 6 7 +sun% + +vax% \fBwriter | reader\fP +0 1 2 3 4 5 6 7 +vax% + +sun% \fBwriter | rsh vax reader\fP +0 1 2 3 4 5 6 7 +sun% +.DE +.SH +Note: +.I +.IX XDR "portable data" +Integers are just the tip of the portable-data iceberg. Arbitrary +data structures present portability problems, particularly with +respect to alignment and pointers. Alignment on word boundaries +may cause the size of a structure to vary from machine to machine. +And pointers, which are very convenient to use, have no meaning +outside the machine where they are defined. +.LP +.NH 1 +\&A Canonical Standard +.IX XDR "canonical standard" +.LP +XDR's approach to standardizing data representations is +.I canonical . +That is, XDR defines a single byte order (Big Endian), a single +floating-point representation (IEEE), and so on. Any program running on +any machine can use XDR to create portable data by translating its +local representation to the XDR standard representations; similarly, any +program running on any machine can read portable data by translating the +XDR standard representaions to its local equivalents. The single standard +completely decouples programs that create or send portable data from those +that use or receive portable data. The advent of a new machine or a new +language has no effect upon the community of existing portable data creators +and users. A new machine joins this community by being \*Qtaught\*U how to +convert the standard representations and its local representations; the +local representations of other machines are irrelevant. Conversely, to +existing programs running on other machines, the local representations of +the new machine are also irrelevant; such programs can immediately read +portable data produced by the new machine because such data conforms to the +canonical standards that they already understand. +.LP +There are strong precedents for XDR's canonical approach. For example, +TCP/IP, UDP/IP, XNS, Ethernet, and, indeed, all protocols below layer five +of the ISO model, are canonical protocols. The advantage of any canonical +approach is simplicity; in the case of XDR, a single set of conversion +routines is written once and is never touched again. The canonical approach +has a disadvantage, but it is unimportant in real-world data transfer +applications. Suppose two Little-Endian machines are transferring integers +according to the XDR standard. The sending machine converts the integers +from Little-Endian byte order to XDR (Big-Endian) byte order; the receiving +machine performs the reverse conversion. Because both machines observe the +same byte order, their conversions are unnecessary. The point, however, is +not necessity, but cost as compared to the alternative. +.LP +The time spent converting to and from a canonical representation is +insignificant, especially in networking applications. Most of the time +required to prepare a data structure for transfer is not spent in conversion +but in traversing the elements of the data structure. To transmit a tree, +for example, each leaf must be visited and each element in a leaf record must +be copied to a buffer and aligned there; storage for the leaf may have to be +deallocated as well. Similarly, to receive a tree, storage must be +allocated for each leaf, data must be moved from the buffer to the leaf and +properly aligned, and pointers must be constructed to link the leaves +together. Every machine pays the cost of traversing and copying data +structures whether or not conversion is required. In networking +applications, communications overhead\(emthe time required to move the data +down through the sender's protocol layers, across the network and up through +the receiver's protocol layers\(emdwarfs conversion overhead. +.NH 1 +\&The XDR Library +.IX "XDR" "library" +.LP +The XDR library not only solves data portability problems, it also +allows you to write and read arbitrary C constructs in a consistent, +specified, well-documented manner. Thus, it can make sense to use the +library even when the data is not shared among machines on a network. +.LP +The XDR library has filter routines for +strings (null-terminated arrays of bytes), +structures, unions, and arrays, to name a few. +Using more primitive routines, +you can write your own specific XDR routines +to describe arbitrary data structures, +including elements of arrays, arms of unions, +or objects pointed at from other structures. +The structures themselves may contain arrays of arbitrary elements, +or pointers to other structures. +.LP +Let's examine the two programs more closely. +There is a family of XDR stream creation routines +in which each member treats the stream of bits differently. +In our example, data is manipulated using standard I/O routines, +so we use +.I xdrstdio_create (). +.IX xdrstdio_create() "" "\fIxdrstdio_create()\fP" +The parameters to XDR stream creation routines +vary according to their function. +In our example, +.I xdrstdio_create() +takes a pointer to an XDR structure that it initializes, +a pointer to a +.I FILE +that the input or output is performed on, and the operation. +The operation may be +.I XDR_ENCODE +for serializing in the +.I writer +program, or +.I XDR_DECODE +for deserializing in the +.I reader +program. +.LP +Note: RPC users never need to create XDR streams; +the RPC system itself creates these streams, +which are then passed to the users. +.LP +The +.I xdr_long() +.IX xdr_long() "" "\fIxdr_long()\fP" +primitive is characteristic of most XDR library +primitives and all client XDR routines. +First, the routine returns +.I FALSE +(0) if it fails, and +.I TRUE +(1) if it succeeds. +Second, for each data type, +.I xxx , +there is an associated XDR routine of the form: +.DS +.ft CW +xdr_xxx(xdrs, xp) + XDR *xdrs; + xxx *xp; +{ +} +.DE +In our case, +.I xxx +is long, and the corresponding XDR routine is +a primitive, +.I xdr_long() . +The client could also define an arbitrary structure +.I xxx +in which case the client would also supply the routine +.I xdr_xxx (), +describing each field by calling XDR routines +of the appropriate type. +In all cases the first parameter, +.I xdrs +can be treated as an opaque handle, +and passed to the primitive routines. +.LP +XDR routines are direction independent; +that is, the same routines are called to serialize or deserialize data. +This feature is critical to software engineering of portable data. +The idea is to call the same routine for either operation \(em +this almost guarantees that serialized data can also be deserialized. +One routine is used by both producer and consumer of networked data. +This is implemented by always passing the address +of an object rather than the object itself \(em +only in the case of deserialization is the object modified. +This feature is not shown in our trivial example, +but its value becomes obvious when nontrivial data structures +are passed among machines. +If needed, the user can obtain the +direction of the XDR operation. +See the +.I "XDR Operation Directions" +section below for details. +.LP +Let's look at a slightly more complicated example. +Assume that a person's gross assets and liabilities +are to be exchanged among processes. +Also assume that these values are important enough +to warrant their own data type: +.ie t .DS +.el .DS L +.ft CW +struct gnumbers { + long g_assets; + long g_liabilities; +}; +.DE +The corresponding XDR routine describing this structure would be: +.ie t .DS +.el .DS L +.ft CW +bool_t /* \fITRUE is success, FALSE is failure\fP */ +xdr_gnumbers(xdrs, gp) + XDR *xdrs; + struct gnumbers *gp; +{ + if (xdr_long(xdrs, &gp->g_assets) && + xdr_long(xdrs, &gp->g_liabilities)) + return(TRUE); + return(FALSE); +} +.DE +Note that the parameter +.I xdrs +is never inspected or modified; +it is only passed on to the subcomponent routines. +It is imperative to inspect the return value of each XDR routine call, +and to give up immediately and return +.I FALSE +if the subroutine fails. +.LP +This example also shows that the type +.I bool_t +is declared as an integer whose only values are +.I TRUE +(1) and +.I FALSE +(0). This document uses the following definitions: +.ie t .DS +.el .DS L +.ft CW +#define bool_t int +#define TRUE 1 +#define FALSE 0 +.DE +.LP +Keeping these conventions in mind, +.I xdr_gnumbers() +can be rewritten as follows: +.ie t .DS +.el .DS L +.ft CW +xdr_gnumbers(xdrs, gp) + XDR *xdrs; + struct gnumbers *gp; +{ + return(xdr_long(xdrs, &gp->g_assets) && + xdr_long(xdrs, &gp->g_liabilities)); +} +.DE +This document uses both coding styles. +.NH 1 +\&XDR Library Primitives +.IX "library primitives for XDR" +.IX XDR "library primitives" +.LP +This section gives a synopsis of each XDR primitive. +It starts with basic data types and moves on to constructed data types. +Finally, XDR utilities are discussed. +The interface to these primitives +and utilities is defined in the include file +.I , +automatically included by +.I . +.NH 2 +\&Number Filters +.IX "XDR library" "number filters" +.LP +The XDR library provides primitives to translate between numbers +and their corresponding external representations. +Primitives cover the set of numbers in: +.DS +.ft CW +[signed, unsigned] * [short, int, long] +.DE +.ne 2i +Specifically, the eight primitives are: +.DS +.ft CW +bool_t xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +.sp.5 +bool_t xdr_u_char(xdrs, ucp) + XDR *xdrs; + unsigned char *ucp; +.sp.5 +bool_t xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +.sp.5 +bool_t xdr_u_int(xdrs, up) + XDR *xdrs; + unsigned *up; +.sp.5 +bool_t xdr_long(xdrs, lip) + XDR *xdrs; + long *lip; +.sp.5 +bool_t xdr_u_long(xdrs, lup) + XDR *xdrs; + u_long *lup; +.sp.5 +bool_t xdr_short(xdrs, sip) + XDR *xdrs; + short *sip; +.sp.5 +bool_t xdr_u_short(xdrs, sup) + XDR *xdrs; + u_short *sup; +.DE +The first parameter, +.I xdrs , +is an XDR stream handle. +The second parameter is the address of the number +that provides data to the stream or receives data from it. +All routines return +.I TRUE +if they complete successfully, and +.I FALSE +otherwise. +.NH 2 +\&Floating Point Filters +.IX "XDR library" "floating point filters" +.LP +The XDR library also provides primitive routines +for C's floating point types: +.DS +.ft CW +bool_t xdr_float(xdrs, fp) + XDR *xdrs; + float *fp; +.sp.5 +bool_t xdr_double(xdrs, dp) + XDR *xdrs; + double *dp; +.DE +The first parameter, +.I xdrs +is an XDR stream handle. +The second parameter is the address +of the floating point number that provides data to the stream +or receives data from it. +Both routines return +.I TRUE +if they complete successfully, and +.I FALSE +otherwise. +.LP +Note: Since the numbers are represented in IEEE floating point, +routines may fail when decoding a valid IEEE representation +into a machine-specific representation, or vice-versa. +.NH 2 +\&Enumeration Filters +.IX "XDR library" "enumeration filters" +.LP +The XDR library provides a primitive for generic enumerations. +The primitive assumes that a C +.I enum +has the same representation inside the machine as a C integer. +The boolean type is an important instance of the +.I enum . +The external representation of a boolean is always +.I TRUE +(1) or +.I FALSE +(0). +.DS +.ft CW +#define bool_t int +#define FALSE 0 +#define TRUE 1 +.sp.5 +#define enum_t int +.sp.5 +bool_t xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +.sp.5 +bool_t xdr_bool(xdrs, bp) + XDR *xdrs; + bool_t *bp; +.DE +The second parameters +.I ep +and +.I bp +are addresses of the associated type that provides data to, or +receives data from, the stream +.I xdrs . +.NH 2 +\&No Data +.IX "XDR library" "no data" +.LP +Occasionally, an XDR routine must be supplied to the RPC system, +even when no data is passed or required. +The library provides such a routine: +.DS +.ft CW +bool_t xdr_void(); /* \fIalways returns TRUE\fP */ +.DE +.NH 2 +\&Constructed Data Type Filters +.IX "XDR library" "constructed data type filters" +.LP +Constructed or compound data type primitives +require more parameters and perform more complicated functions +then the primitives discussed above. +This section includes primitives for +strings, arrays, unions, and pointers to structures. +.LP +Constructed data type primitives may use memory management. +In many cases, memory is allocated when deserializing data with +.I XDR_DECODE +Therefore, the XDR package must provide means to deallocate memory. +This is done by an XDR operation, +.I XDR_FREE +To review, the three XDR directional operations are +.I XDR_ENCODE , +.I XDR_DECODE +and +.I XDR_FREE . +.NH 3 +\&Strings +.IX "XDR library" "strings" +.LP +In C, a string is defined as a sequence of bytes +terminated by a null byte, +which is not considered when calculating string length. +However, when a string is passed or manipulated, +a pointer to it is employed. +Therefore, the XDR library defines a string to be a +.I "char *" +and not a sequence of characters. +The external representation of a string is drastically different +from its internal representation. +Externally, strings are represented as +sequences of ASCII characters, +while internally, they are represented with character pointers. +Conversion between the two representations +is accomplished with the routine +.I xdr_string (): +.IX xdr_string() "" \fIxdr_string()\fP +.DS +.ft CW +bool_t xdr_string(xdrs, sp, maxlength) + XDR *xdrs; + char **sp; + u_int maxlength; +.DE +The first parameter +.I xdrs +is the XDR stream handle. +The second parameter +.I sp +is a pointer to a string (type +.I "char **" . +The third parameter +.I maxlength +specifies the maximum number of bytes allowed during encoding or decoding. +its value is usually specified by a protocol. For example, a protocol +specification may say that a file name may be no longer than 255 characters. +.LP +The routine returns +.I FALSE +if the number of characters exceeds +.I maxlength , +and +.I TRUE +if it doesn't. +.SH +Keep +.I maxlength +small. If it is too big you can blow the heap, since +.I xdr_string() +will call +.I malloc() +for space. +.LP +The behavior of +.I xdr_string() +.IX xdr_string() "" \fIxdr_string()\fP +is similar to the behavior of other routines +discussed in this section. The direction +.I XDR_ENCODE +is easiest to understand. The parameter +.I sp +points to a string of a certain length; +if the string does not exceed +.I maxlength , +the bytes are serialized. +.LP +The effect of deserializing a string is subtle. +First the length of the incoming string is determined; +it must not exceed +.I maxlength . +Next +.I sp +is dereferenced; if the the value is +.I NULL , +then a string of the appropriate length is allocated and +.I *sp +is set to this string. +If the original value of +.I *sp +is non-null, then the XDR package assumes +that a target area has been allocated, +which can hold strings no longer than +.I maxlength . +In either case, the string is decoded into the target area. +The routine then appends a null character to the string. +.LP +In the +.I XDR_FREE +operation, the string is obtained by dereferencing +.I sp . +If the string is not +.I NULL , +it is freed and +.I *sp +is set to +.I NULL . +In this operation, +.I xdr_string() +ignores the +.I maxlength +parameter. +.NH 3 +\&Byte Arrays +.IX "XDR library" "byte arrays" +.LP +Often variable-length arrays of bytes are preferable to strings. +Byte arrays differ from strings in the following three ways: +1) the length of the array (the byte count) is explicitly +located in an unsigned integer, +2) the byte sequence is not terminated by a null character, and +3) the external representation of the bytes is the same as their +internal representation. +The primitive +.I xdr_bytes() +.IX xdr_bytes() "" \fIxdr_bytes()\fP +converts between the internal and external +representations of byte arrays: +.DS +.ft CW +bool_t xdr_bytes(xdrs, bpp, lp, maxlength) + XDR *xdrs; + char **bpp; + u_int *lp; + u_int maxlength; +.DE +The usage of the first, second and fourth parameters +are identical to the first, second and third parameters of +.I xdr_string (), +respectively. +The length of the byte area is obtained by dereferencing +.I lp +when serializing; +.I *lp +is set to the byte length when deserializing. +.NH 3 +\&Arrays +.IX "XDR library" "arrays" +.LP +The XDR library package provides a primitive +for handling arrays of arbitrary elements. +The +.I xdr_bytes() +routine treats a subset of generic arrays, +in which the size of array elements is known to be 1, +and the external description of each element is built-in. +The generic array primitive, +.I xdr_array() , +.IX xdr_array() "" \fIxdr_array()\fP +requires parameters identical to those of +.I xdr_bytes() +plus two more: +the size of array elements, +and an XDR routine to handle each of the elements. +This routine is called to encode or decode +each element of the array. +.DS +.ft CW +bool_t +xdr_array(xdrs, ap, lp, maxlength, elementsiz, xdr_element) + XDR *xdrs; + char **ap; + u_int *lp; + u_int maxlength; + u_int elementsiz; + bool_t (*xdr_element)(); +.DE +The parameter +.I ap +is the address of the pointer to the array. +If +.I *ap +is +.I NULL +when the array is being deserialized, +XDR allocates an array of the appropriate size and sets +.I *ap +to that array. +The element count of the array is obtained from +.I *lp +when the array is serialized; +.I *lp +is set to the array length when the array is deserialized. +The parameter +.I maxlength +is the maximum number of elements that the array is allowed to have; +.I elementsiz +is the byte size of each element of the array +(the C function +.I sizeof() +can be used to obtain this value). +The +.I xdr_element() +.IX xdr_element() "" \fIxdr_element()\fP +routine is called to serialize, deserialize, or free +each element of the array. +.br +.LP +Before defining more constructed data types, it is appropriate to +present three examples. +.LP +.I "Example A:" +.br +A user on a networked machine can be identified by +(a) the machine name, such as +.I krypton : +see the +.I gethostname +man page; (b) the user's UID: see the +.I geteuid +man page; and (c) the group numbers to which the user belongs: +see the +.I getgroups +man page. A structure with this information and its associated +XDR routine could be coded like this: +.ie t .DS +.el .DS L +.ft CW +struct netuser { + char *nu_machinename; + int nu_uid; + u_int nu_glen; + int *nu_gids; +}; +#define NLEN 255 /* \fImachine names < 256 chars\fP */ +#define NGRPS 20 /* \fIuser can't be in > 20 groups\fP */ +.sp.5 +bool_t +xdr_netuser(xdrs, nup) + XDR *xdrs; + struct netuser *nup; +{ + return(xdr_string(xdrs, &nup->nu_machinename, NLEN) && + xdr_int(xdrs, &nup->nu_uid) && + xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen, + NGRPS, sizeof (int), xdr_int)); +} +.DE +.LP +.I "Example B:" +.br +A party of network users could be implemented +as an array of +.I netuser +structure. +The declaration and its associated XDR routines +are as follows: +.ie t .DS +.el .DS L +.ft CW +struct party { + u_int p_len; + struct netuser *p_nusers; +}; +#define PLEN 500 /* \fImax number of users in a party\fP */ +.sp.5 +bool_t +xdr_party(xdrs, pp) + XDR *xdrs; + struct party *pp; +{ + return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN, + sizeof (struct netuser), xdr_netuser)); +} +.DE +.LP +.I "Example C:" +.br +The well-known parameters to +.I main , +.I argc +and +.I argv +can be combined into a structure. +An array of these structures can make up a history of commands. +The declarations and XDR routines might look like: +.ie t .DS +.el .DS L +.ft CW +struct cmd { + u_int c_argc; + char **c_argv; +}; +#define ALEN 1000 /* \fIargs cannot be > 1000 chars\fP */ +#define NARGC 100 /* \fIcommands cannot have > 100 args\fP */ + +struct history { + u_int h_len; + struct cmd *h_cmds; +}; +#define NCMDS 75 /* \fIhistory is no more than 75 commands\fP */ + +bool_t +xdr_wrap_string(xdrs, sp) + XDR *xdrs; + char **sp; +{ + return(xdr_string(xdrs, sp, ALEN)); +} +.DE +.ie t .DS +.el .DS L +.ft CW +bool_t +xdr_cmd(xdrs, cp) + XDR *xdrs; + struct cmd *cp; +{ + return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC, + sizeof (char *), xdr_wrap_string)); +} +.DE +.ie t .DS +.el .DS L +.ft CW +bool_t +xdr_history(xdrs, hp) + XDR *xdrs; + struct history *hp; +{ + return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS, + sizeof (struct cmd), xdr_cmd)); +} +.DE +The most confusing part of this example is that the routine +.I xdr_wrap_string() +is needed to package the +.I xdr_string() +routine, because the implementation of +.I xdr_array() +only passes two parameters to the array element description routine; +.I xdr_wrap_string() +supplies the third parameter to +.I xdr_string (). +.LP +By now the recursive nature of the XDR library should be obvious. +Let's continue with more constructed data types. +.NH 3 +\&Opaque Data +.IX "XDR library" "opaque data" +.LP +In some protocols, handles are passed from a server to client. +The client passes the handle back to the server at some later time. +Handles are never inspected by clients; +they are obtained and submitted. +That is to say, handles are opaque. +The +.I xdr_opaque() +.IX xdr_opaque() "" \fIxdr_opaque()\fP +primitive is used for describing fixed sized, opaque bytes. +.DS +.ft CW +bool_t xdr_opaque(xdrs, p, len) + XDR *xdrs; + char *p; + u_int len; +.DE +The parameter +.I p +is the location of the bytes; +.I len +is the number of bytes in the opaque object. +By definition, the actual data +contained in the opaque object are not machine portable. +.NH 3 +\&Fixed Sized Arrays +.IX "XDR library" "fixed sized arrays" +.LP +The XDR library provides a primitive, +.I xdr_vector (), +for fixed-length arrays. +.ie t .DS +.el .DS L +.ft CW +#define NLEN 255 /* \fImachine names must be < 256 chars\fP */ +#define NGRPS 20 /* \fIuser belongs to exactly 20 groups\fP */ +.sp.5 +struct netuser { + char *nu_machinename; + int nu_uid; + int nu_gids[NGRPS]; +}; +.sp.5 +bool_t +xdr_netuser(xdrs, nup) + XDR *xdrs; + struct netuser *nup; +{ + int i; +.sp.5 + if (!xdr_string(xdrs, &nup->nu_machinename, NLEN)) + return(FALSE); + if (!xdr_int(xdrs, &nup->nu_uid)) + return(FALSE); + if (!xdr_vector(xdrs, nup->nu_gids, NGRPS, sizeof(int), + xdr_int)) { + return(FALSE); + } + return(TRUE); +} +.DE +.NH 3 +\&Discriminated Unions +.IX "XDR library" "discriminated unions" +.LP +The XDR library supports discriminated unions. +A discriminated union is a C union and an +.I enum_t +value that selects an \*Qarm\*U of the union. +.DS +.ft CW +struct xdr_discrim { + enum_t value; + bool_t (*proc)(); +}; +.sp.5 +bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm) + XDR *xdrs; + enum_t *dscmp; + char *unp; + struct xdr_discrim *arms; + bool_t (*defaultarm)(); /* \fImay equal NULL\fP */ +.DE +First the routine translates the discriminant of the union located at +.I *dscmp . +The discriminant is always an +.I enum_t . +Next the union located at +.I *unp +is translated. +The parameter +.I arms +is a pointer to an array of +.I xdr_discrim +structures. +Each structure contains an ordered pair of +.I [value,proc] . +If the union's discriminant is equal to the associated +.I value , +then the +.I proc +is called to translate the union. +The end of the +.I xdr_discrim +structure array is denoted by a routine of value +.I NULL +(0). If the discriminant is not found in the +.I arms +array, then the +.I defaultarm +procedure is called if it is non-null; +otherwise the routine returns +.I FALSE . +.LP +.I "Example D:" +Suppose the type of a union may be integer, +character pointer (a string), or a +.I gnumbers +structure. +Also, assume the union and its current type +are declared in a structure. +The declaration is: +.ie t .DS +.el .DS L +.ft CW +enum utype { INTEGER=1, STRING=2, GNUMBERS=3 }; +.sp.5 +struct u_tag { + enum utype utype; /* \fIthe union's discriminant\fP */ + union { + int ival; + char *pval; + struct gnumbers gn; + } uval; +}; +.DE +The following constructs and XDR procedure (de)serialize +the discriminated union: +.ie t .DS +.el .DS L +.ft CW +struct xdr_discrim u_tag_arms[4] = { + { INTEGER, xdr_int }, + { GNUMBERS, xdr_gnumbers } + { STRING, xdr_wrap_string }, + { __dontcare__, NULL } + /* \fIalways terminate arms with a NULL xdr_proc\fP */ +} +.sp.5 +bool_t +xdr_u_tag(xdrs, utp) + XDR *xdrs; + struct u_tag *utp; +{ + return(xdr_union(xdrs, &utp->utype, &utp->uval, + u_tag_arms, NULL)); +} +.DE +The routine +.I xdr_gnumbers() +was presented above in +.I "The XDR Library" +section. +.I xdr_wrap_string() +was presented in example C. +The default +.I arm +parameter to +.I xdr_union() +(the last parameter) is +.I NULL +in this example. Therefore the value of the union's discriminant +may legally take on only values listed in the +.I u_tag_arms +array. This example also demonstrates that +the elements of the arm's array do not need to be sorted. +.LP +It is worth pointing out that the values of the discriminant +may be sparse, though in this example they are not. +It is always good +practice to assign explicitly integer values to each element of the +discriminant's type. +This practice both documents the external +representation of the discriminant and guarantees that different +C compilers emit identical discriminant values. +.LP +Exercise: Implement +.I xdr_union() +using the other primitives in this section. +.NH 3 +\&Pointers +.IX "XDR library" "pointers" +.LP +In C it is often convenient to put pointers +to another structure within a structure. +The +.I xdr_reference() +.IX xdr_reference() "" \fIxdr_reference()\fP +primitive makes it easy to serialize, deserialize, and free +these referenced structures. +.DS +.ft CW +bool_t xdr_reference(xdrs, pp, size, proc) + XDR *xdrs; + char **pp; + u_int ssize; + bool_t (*proc)(); +.DE +.LP +Parameter +.I pp +is the address of +the pointer to the structure; +parameter +.I ssize +is the size in bytes of the structure (use the C function +.I sizeof() +to obtain this value); and +.I proc +is the XDR routine that describes the structure. +When decoding data, storage is allocated if +.I *pp +is +.I NULL . +.LP +There is no need for a primitive +.I xdr_struct() +to describe structures within structures, +because pointers are always sufficient. +.LP +Exercise: Implement +.I xdr_reference() +using +.I xdr_array (). +Warning: +.I xdr_reference() +and +.I xdr_array() +are NOT interchangeable external representations of data. +.LP +.I "Example E:" +Suppose there is a structure containing a person's name +and a pointer to a +.I gnumbers +structure containing the person's gross assets and liabilities. +The construct is: +.DS +.ft CW +struct pgn { + char *name; + struct gnumbers *gnp; +}; +.DE +The corresponding XDR routine for this structure is: +.DS +.ft CW +bool_t +xdr_pgn(xdrs, pp) + XDR *xdrs; + struct pgn *pp; +{ + if (xdr_string(xdrs, &pp->name, NLEN) && + xdr_reference(xdrs, &pp->gnp, + sizeof(struct gnumbers), xdr_gnumbers)) + return(TRUE); + return(FALSE); +} +.DE +.IX "pointer semantics and XDR" +.I "Pointer Semantics and XDR" +.LP +In many applications, C programmers attach double meaning to +the values of a pointer. Typically the value +.I NULL +(or zero) means data is not needed, +yet some application-specific interpretation applies. +In essence, the C programmer is encoding +a discriminated union efficiently +by overloading the interpretation of the value of a pointer. +For instance, in example E a +.I NULL +pointer value for +.I gnp +could indicate that +the person's assets and liabilities are unknown. +That is, the pointer value encodes two things: +whether or not the data is known; +and if it is known, where it is located in memory. +Linked lists are an extreme example of the use +of application-specific pointer interpretation. +.LP +The primitive +.I xdr_reference() +.IX xdr_reference() "" \fIxdr_reference()\fP +cannot and does not attach any special +meaning to a null-value pointer during serialization. +That is, passing an address of a pointer whose value is +.I NULL +to +.I xdr_reference() +when serialing data will most likely cause a memory fault and, on the UNIX +system, a core dump. +.LP +.I xdr_pointer() +correctly handles +.I NULL +pointers. For more information about its use, see +the +.I "Linked Lists" +topics below. +.LP +.I Exercise: +After reading the section on +.I "Linked Lists" , +return here and extend example E so that +it can correctly deal with +.I NULL +pointer values. +.LP +.I Exercise: +Using the +.I xdr_union (), +.I xdr_reference() +and +.I xdr_void() +primitives, implement a generic pointer handling primitive +that implicitly deals with +.I NULL +pointers. That is, implement +.I xdr_pointer (). +.NH 2 +\&Non-filter Primitives +.IX "XDR" "non-filter primitives" +.LP +XDR streams can be manipulated with +the primitives discussed in this section. +.DS +.ft CW +u_int xdr_getpos(xdrs) + XDR *xdrs; +.sp.5 +bool_t xdr_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +.sp.5 +xdr_destroy(xdrs) + XDR *xdrs; +.DE +The routine +.I xdr_getpos() +.IX xdr_getpos() "" \fIxdr_getpos()\fP +returns an unsigned integer +that describes the current position in the data stream. +Warning: In some XDR streams, the returned value of +.I xdr_getpos() +is meaningless; +the routine returns a \-1 in this case +(though \-1 should be a legitimate value). +.LP +The routine +.I xdr_setpos() +.IX xdr_setpos() "" \fIxdr_setpos()\fP +sets a stream position to +.I pos . +Warning: In some XDR streams, setting a position is impossible; +in such cases, +.I xdr_setpos() +will return +.I FALSE . +This routine will also fail if the requested position is out-of-bounds. +The definition of bounds varies from stream to stream. +.LP +The +.I xdr_destroy() +.IX xdr_destroy() "" \fIxdr_destroy()\fP +primitive destroys the XDR stream. +Usage of the stream +after calling this routine is undefined. +.NH 2 +\&XDR Operation Directions +.IX XDR "operation directions" +.IX "direction of XDR operations" +.LP +At times you may wish to optimize XDR routines by taking +advantage of the direction of the operation \(em +.I XDR_ENCODE +.I XDR_DECODE +or +.I XDR_FREE +The value +.I xdrs->x_op +always contains the direction of the XDR operation. +Programmers are not encouraged to take advantage of this information. +Therefore, no example is presented here. However, an example in the +.I "Linked Lists" +topic below, demonstrates the usefulness of the +.I xdrs->x_op +field. +.NH 2 +\&XDR Stream Access +.IX "XDR" "stream access" +.LP +An XDR stream is obtained by calling the appropriate creation routine. +These creation routines take arguments that are tailored to the +specific properties of the stream. +.LP +Streams currently exist for (de)serialization of data to or from +standard I/O +.I FILE +streams, TCP/IP connections and UNIX files, and memory. +.NH 3 +\&Standard I/O Streams +.IX "XDR" "standard I/O streams" +.LP +XDR streams can be interfaced to standard I/O using the +.I xdrstdio_create() +.IX xdrstdio_create() "" \fIxdrstdio_create()\fP +routine as follows: +.DS +.ft CW +#include +#include /* \fIxdr streams part of rpc\fP */ +.sp.5 +void +xdrstdio_create(xdrs, fp, x_op) + XDR *xdrs; + FILE *fp; + enum xdr_op x_op; +.DE +The routine +.I xdrstdio_create() +initializes an XDR stream pointed to by +.I xdrs . +The XDR stream interfaces to the standard I/O library. +Parameter +.I fp +is an open file, and +.I x_op +is an XDR direction. +.NH 3 +\&Memory Streams +.IX "XDR" "memory streams" +.LP +Memory streams allow the streaming of data into or out of +a specified area of memory: +.DS +.ft CW +#include +.sp.5 +void +xdrmem_create(xdrs, addr, len, x_op) + XDR *xdrs; + char *addr; + u_int len; + enum xdr_op x_op; +.DE +The routine +.I xdrmem_create() +.IX xdrmem_create() "" \fIxdrmem_create()\fP +initializes an XDR stream in local memory. +The memory is pointed to by parameter +.I addr ; +parameter +.I len +is the length in bytes of the memory. +The parameters +.I xdrs +and +.I x_op +are identical to the corresponding parameters of +.I xdrstdio_create (). +Currently, the UDP/IP implementation of RPC uses +.I xdrmem_create (). +Complete call or result messages are built in memory before calling the +.I sendto() +system routine. +.NH 3 +\&Record (TCP/IP) Streams +.IX "XDR" "record (TCP/IP) streams" +.LP +A record stream is an XDR stream built on top of +a record marking standard that is built on top of the +UNIX file or 4.2 BSD connection interface. +.DS +.ft CW +#include /* \fIxdr streams part of rpc\fP */ +.sp.5 +xdrrec_create(xdrs, + sendsize, recvsize, iohandle, readproc, writeproc) + XDR *xdrs; + u_int sendsize, recvsize; + char *iohandle; + int (*readproc)(), (*writeproc)(); +.DE +The routine +.I xdrrec_create() +provides an XDR stream interface that allows for a bidirectional, +arbitrarily long sequence of records. +The contents of the records are meant to be data in XDR form. +The stream's primary use is for interfacing RPC to TCP connections. +However, it can be used to stream data into or out of normal +UNIX files. +.LP +The parameter +.I xdrs +is similar to the corresponding parameter described above. +The stream does its own data buffering similar to that of standard I/O. +The parameters +.I sendsize +and +.I recvsize +determine the size in bytes of the output and input buffers, respectively; +if their values are zero (0), then predetermined defaults are used. +When a buffer needs to be filled or flushed, the routine +.I readproc() +or +.I writeproc() +is called, respectively. +The usage and behavior of these +routines are similar to the UNIX system calls +.I read() +and +.I write (). +However, +the first parameter to each of these routines is the opaque parameter +.I iohandle . +The other two parameters +.I buf "" +and +.I nbytes ) +and the results +(byte count) are identical to the system routines. +If +.I xxx +is +.I readproc() +or +.I writeproc (), +then it has the following form: +.DS +.ft CW +.ft I +/* + * returns the actual number of bytes transferred. + * -1 is an error + */ +.ft CW +int +xxx(iohandle, buf, len) + char *iohandle; + char *buf; + int nbytes; +.DE +The XDR stream provides means for delimiting records in the byte stream. +The implementation details of delimiting records in a stream are +discussed in the +.I "Advanced Topics" +topic below. +The primitives that are specific to record streams are as follows: +.DS +.ft CW +bool_t +xdrrec_endofrecord(xdrs, flushnow) + XDR *xdrs; + bool_t flushnow; +.sp.5 +bool_t +xdrrec_skiprecord(xdrs) + XDR *xdrs; +.sp.5 +bool_t +xdrrec_eof(xdrs) + XDR *xdrs; +.DE +The routine +.I xdrrec_endofrecord() +.IX xdrrec_endofrecord() "" \fIxdrrec_endofrecord()\fP +causes the current outgoing data to be marked as a record. +If the parameter +.I flushnow +is +.I TRUE , +then the stream's +.I writeproc +will be called; otherwise, +.I writeproc +will be called when the output buffer has been filled. +.LP +The routine +.I xdrrec_skiprecord() +.IX xdrrec_skiprecord() "" \fIxdrrec_skiprecord()\fP +causes an input stream's position to be moved past +the current record boundary and onto the +beginning of the next record in the stream. +.LP +If there is no more data in the stream's input buffer, +then the routine +.I xdrrec_eof() +.IX xdrrec_eof() "" \fIxdrrec_eof()\fP +returns +.I TRUE . +That is not to say that there is no more data +in the underlying file descriptor. +.NH 2 +\&XDR Stream Implementation +.IX "XDR" "stream implementation" +.IX "stream implementation in XDR" +.LP +This section provides the abstract data types needed +to implement new instances of XDR streams. +.NH 3 +\&The XDR Object +.IX "XDR" "object" +.LP +The following structure defines the interface to an XDR stream: +.ie t .DS +.el .DS L +.ft CW +enum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 }; +.sp.5 +typedef struct { + enum xdr_op x_op; /* \fIoperation; fast added param\fP */ + struct xdr_ops { + bool_t (*x_getlong)(); /* \fIget long from stream\fP */ + bool_t (*x_putlong)(); /* \fIput long to stream\fP */ + bool_t (*x_getbytes)(); /* \fIget bytes from stream\fP */ + bool_t (*x_putbytes)(); /* \fIput bytes to stream\fP */ + u_int (*x_getpostn)(); /* \fIreturn stream offset\fP */ + bool_t (*x_setpostn)(); /* \fIreposition offset\fP */ + caddr_t (*x_inline)(); /* \fIptr to buffered data\fP */ + VOID (*x_destroy)(); /* \fIfree private area\fP */ + } *x_ops; + caddr_t x_public; /* \fIusers' data\fP */ + caddr_t x_private; /* \fIpointer to private data\fP */ + caddr_t x_base; /* \fIprivate for position info\fP */ + int x_handy; /* \fIextra private word\fP */ +} XDR; +.DE +The +.I x_op +field is the current operation being performed on the stream. +This field is important to the XDR primitives, +but should not affect a stream's implementation. +That is, a stream's implementation should not depend +on this value. +The fields +.I x_private , +.I x_base , +and +.I x_handy +are private to the particular +stream's implementation. +The field +.I x_public +is for the XDR client and should never be used by +the XDR stream implementations or the XDR primitives. +.I x_getpostn() , +.I x_setpostn() +and +.I x_destroy() +are macros for accessing operations. The operation +.I x_inline() +takes two parameters: +an XDR *, and an unsigned integer, which is a byte count. +The routine returns a pointer to a piece of +the stream's internal buffer. +The caller can then use the buffer segment for any purpose. +From the stream's point of view, the bytes in the +buffer segment have been consumed or put. +The routine may return +.I NULL +if it cannot return a buffer segment of the requested size. +(The +.I x_inline() +routine is for cycle squeezers. +Use of the resulting buffer is not data-portable. +Users are encouraged not to use this feature.) +.LP +The operations +.I x_getbytes() +and +.I x_putbytes() +blindly get and put sequences of bytes +from or to the underlying stream; +they return +.I TRUE +if they are successful, and +.I FALSE +otherwise. The routines have identical parameters (replace +.I xxx ): +.DS +.ft CW +bool_t +xxxbytes(xdrs, buf, bytecount) + XDR *xdrs; + char *buf; + u_int bytecount; +.DE +The operations +.I x_getlong() +and +.I x_putlong() +receive and put +long numbers from and to the data stream. +It is the responsibility of these routines +to translate the numbers between the machine representation +and the (standard) external representation. +The UNIX primitives +.I htonl() +and +.I ntohl() +can be helpful in accomplishing this. +The higher-level XDR implementation assumes that +signed and unsigned long integers contain the same number of bits, +and that nonnegative integers +have the same bit representations as unsigned integers. +The routines return +.I TRUE +if they succeed, and +.I FALSE +otherwise. They have identical parameters: +.DS +.ft CW +bool_t +xxxlong(xdrs, lp) + XDR *xdrs; + long *lp; +.DE +Implementors of new XDR streams must make an XDR structure +(with new operation routines) available to clients, +using some kind of create routine. +.NH 1 +\&Advanced Topics +.IX XDR "advanced topics" +.LP +This section describes techniques for passing data structures that +are not covered in the preceding sections. Such structures include +linked lists (of arbitrary lengths). Unlike the simpler examples +covered in the earlier sections, the following examples are written +using both the XDR C library routines and the XDR data description +language. +The +.I "External Data Representation Standard: Protocol Specification" +describes this +language in complete detail. +.NH 2 +\&Linked Lists +.IX XDR "linked lists" +.LP +The last example in the +.I Pointers +topic earlier in this chapter +presented a C data structure and its associated XDR +routines for a individual's gross assets and liabilities. +The example is duplicated below: +.ie t .DS +.el .DS L +.ft CW +struct gnumbers { + long g_assets; + long g_liabilities; +}; +.sp.5 +bool_t +xdr_gnumbers(xdrs, gp) + XDR *xdrs; + struct gnumbers *gp; +{ + if (xdr_long(xdrs, &(gp->g_assets))) + return(xdr_long(xdrs, &(gp->g_liabilities))); + return(FALSE); +} +.DE +.LP +Now assume that we wish to implement a linked list of such information. +A data structure could be constructed as follows: +.ie t .DS +.el .DS L +.ft CW +struct gnumbers_node { + struct gnumbers gn_numbers; + struct gnumbers_node *gn_next; +}; +.sp .5 +typedef struct gnumbers_node *gnumbers_list; +.DE +.LP +The head of the linked list can be thought of as the data object; +that is, the head is not merely a convenient shorthand for a +structure. Similarly the +.I gn_next +field is used to indicate whether or not the object has terminated. +Unfortunately, if the object continues, the +.I gn_next +field is also the address of where it continues. The link addresses +carry no useful information when the object is serialized. +.LP +The XDR data description of this linked list is described by the +recursive declaration of +.I gnumbers_list : +.ie t .DS +.el .DS L +.ft CW +struct gnumbers { + int g_assets; + int g_liabilities; +}; +.sp .5 +struct gnumbers_node { + gnumbers gn_numbers; + gnumbers_node *gn_next; +}; +.DE +.LP +In this description, the boolean indicates whether there is more data +following it. If the boolean is +.I FALSE , +then it is the last data field of the structure. If it is +.I TRUE , +then it is followed by a gnumbers structure and (recursively) by a +.I gnumbers_list . +Note that the C declaration has no boolean explicitly declared in it +(though the +.I gn_next +field implicitly carries the information), while the XDR data +description has no pointer explicitly declared in it. +.LP +Hints for writing the XDR routines for a +.I gnumbers_list +follow easily from the XDR description above. Note how the primitive +.I xdr_pointer() +is used to implement the XDR union above. +.ie t .DS +.el .DS L +.ft CW +bool_t +xdr_gnumbers_node(xdrs, gn) + XDR *xdrs; + gnumbers_node *gn; +{ + return(xdr_gnumbers(xdrs, &gn->gn_numbers) && + xdr_gnumbers_list(xdrs, &gp->gn_next)); +} +.sp .5 +bool_t +xdr_gnumbers_list(xdrs, gnp) + XDR *xdrs; + gnumbers_list *gnp; +{ + return(xdr_pointer(xdrs, gnp, + sizeof(struct gnumbers_node), + xdr_gnumbers_node)); +} +.DE +.LP +The unfortunate side effect of XDR'ing a list with these routines +is that the C stack grows linearly with respect to the number of +node in the list. This is due to the recursion. The following +routine collapses the above two mutually recursive into a single, +non-recursive one. +.ie t .DS +.el .DS L +.ft CW +bool_t +xdr_gnumbers_list(xdrs, gnp) + XDR *xdrs; + gnumbers_list *gnp; +{ + bool_t more_data; + gnumbers_list *nextp; +.sp .5 + for (;;) { + more_data = (*gnp != NULL); + if (!xdr_bool(xdrs, &more_data)) { + return(FALSE); + } + if (! more_data) { + break; + } + if (xdrs->x_op == XDR_FREE) { + nextp = &(*gnp)->gn_next; + } + if (!xdr_reference(xdrs, gnp, + sizeof(struct gnumbers_node), xdr_gnumbers)) { + + return(FALSE); + } + gnp = (xdrs->x_op == XDR_FREE) ? + nextp : &(*gnp)->gn_next; + } + *gnp = NULL; + return(TRUE); +} +.DE +.LP +The first task is to find out whether there is more data or not, +so that this boolean information can be serialized. Notice that +this statement is unnecessary in the +.I XDR_DECODE +case, since the value of more_data is not known until we +deserialize it in the next statement. +.LP +The next statement XDR's the more_data field of the XDR union. +Then if there is truly no more data, we set this last pointer to +.I NULL +to indicate the end of the list, and return +.I TRUE +because we are done. Note that setting the pointer to +.I NULL +is only important in the +.I XDR_DECODE +case, since it is already +.I NULL +in the +.I XDR_ENCODE +and +XDR_FREE +cases. +.LP +Next, if the direction is +.I XDR_FREE , +the value of +.I nextp +is set to indicate the location of the next pointer in the list. +We do this now because we need to dereference gnp to find the +location of the next item in the list, and after the next +statement the storage pointed to by +.I gnp +will be freed up and no be longer valid. We can't do this for all +directions though, because in the +.I XDR_DECODE +direction the value of +.I gnp +won't be set until the next statement. +.LP +Next, we XDR the data in the node using the primitive +.I xdr_reference (). +.I xdr_reference() +is like +.I xdr_pointer() +which we used before, but it does not +send over the boolean indicating whether there is more data. +We use it instead of +.I xdr_pointer() +because we have already XDR'd this information ourselves. Notice +that the xdr routine passed is not the same type as an element +in the list. The routine passed is +.I xdr_gnumbers (), +for XDR'ing gnumbers, but each element in the list is actually of +type +.I gnumbers_node . +We don't pass +.I xdr_gnumbers_node() +because it is recursive, and instead use +.I xdr_gnumbers() +which XDR's all of the non-recursive part. Note that this trick +will work only if the +.I gn_numbers +field is the first item in each element, so that their addresses +are identical when passed to +.I xdr_reference (). +.LP +Finally, we update +.I gnp +to point to the next item in the list. If the direction is +.I XDR_FREE , +we set it to the previously saved value, otherwise we can +dereference +.I gnp +to get the proper value. Though harder to understand than the +recursive version, this non-recursive routine is far less likely +to blow the C stack. It will also run more efficiently since +a lot of procedure call overhead has been removed. Most lists +are small though (in the hundreds of items or less) and the +recursive version should be sufficient for them. +.EQ +delim off +.EN diff --git a/c/src/exec/librpc/src/rpc/PSD.doc/xdr.rfc.ms b/c/src/exec/librpc/src/rpc/PSD.doc/xdr.rfc.ms index e69de29bb2..d4baff5391 100644 --- a/c/src/exec/librpc/src/rpc/PSD.doc/xdr.rfc.ms +++ b/c/src/exec/librpc/src/rpc/PSD.doc/xdr.rfc.ms @@ -0,0 +1,1058 @@ +.\" +.\" Must use -- tbl -- with this one +.\" +.\" @(#)xdr.rfc.ms 2.2 88/08/05 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'External Data Representation Standard''Page %' +.EH 'Page %''External Data Representation Standard' +.IX "External Data Representation" +.if \\n%=1 .bp +.SH +\&External Data Representation Standard: Protocol Specification +.IX XDR RFC +.IX XDR "protocol specification" +.LP +.NH 0 +\&Status of this Standard +.nr OF 1 +.IX XDR "RFC status" +.LP +Note: This chapter specifies a protocol that Sun Microsystems, Inc., and +others are using. It has been designated RFC1014 by the ARPA Network +Information Center. +.NH 1 +Introduction +\& +.LP +XDR is a standard for the description and encoding of data. It is +useful for transferring data between different computer +architectures, and has been used to communicate data between such +diverse machines as the Sun Workstation, VAX, IBM-PC, and Cray. +XDR fits into the ISO presentation layer, and is roughly analogous in +purpose to X.409, ISO Abstract Syntax Notation. The major difference +between these two is that XDR uses implicit typing, while X.409 uses +explicit typing. +.LP +XDR uses a language to describe data formats. The language can only +be used only to describe data; it is not a programming language. +This language allows one to describe intricate data formats in a +concise manner. The alternative of using graphical representations +(itself an informal language) quickly becomes incomprehensible when +faced with complexity. The XDR language itself is similar to the C +language [1], just as Courier [4] is similar to Mesa. Protocols such +as Sun RPC (Remote Procedure Call) and the NFS (Network File System) +use XDR to describe the format of their data. +.LP +The XDR standard makes the following assumption: that bytes (or +octets) are portable, where a byte is defined to be 8 bits of data. +A given hardware device should encode the bytes onto the various +media in such a way that other hardware devices may decode the bytes +without loss of meaning. For example, the Ethernet standard +suggests that bytes be encoded in "little-endian" style [2], or least +significant bit first. +.NH 2 +\&Basic Block Size +.IX XDR "basic block size" +.IX XDR "block size" +.LP +The representation of all items requires a multiple of four bytes (or +32 bits) of data. The bytes are numbered 0 through n-1. The bytes +are read or written to some byte stream such that byte m always +precedes byte m+1. If the n bytes needed to contain the data are not +a multiple of four, then the n bytes are followed by enough (0 to 3) +residual zero bytes, r, to make the total byte count a multiple of 4. +.LP +We include the familiar graphic box notation for illustration and +comparison. In most illustrations, each box (delimited by a plus +sign at the 4 corners and vertical bars and dashes) depicts a byte. +Ellipses (...) between boxes show zero or more additional bytes where +required. +.ie t .DS +.el .DS L +\fIA Block\fP + +\f(CW+--------+--------+...+--------+--------+...+--------+ +| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 | ++--------+--------+...+--------+--------+...+--------+ +|<-----------n bytes---------->|<------r bytes------>| +|<-----------n+r (where (n+r) mod 4 = 0)>----------->|\fP + +.DE +.NH 1 +\&XDR Data Types +.IX XDR "data types" +.IX "XDR data types" +.LP +Each of the sections that follow describes a data type defined in the +XDR standard, shows how it is declared in the language, and includes +a graphic illustration of its encoding. +.LP +For each data type in the language we show a general paradigm +declaration. Note that angle brackets (< and >) denote +variable length sequences of data and square brackets ([ and ]) denote +fixed-length sequences of data. "n", "m" and "r" denote integers. +For the full language specification and more formal definitions of +terms such as "identifier" and "declaration", refer to +.I "The XDR Language Specification" , +below. +.LP +For some data types, more specific examples are included. +A more extensive example of a data description is in +.I "An Example of an XDR Data Description" +below. +.NH 2 +\&Integer +.IX XDR integer +.LP +An XDR signed integer is a 32-bit datum that encodes an integer in +the range [-2147483648,2147483647]. The integer is represented in +two's complement notation. The most and least significant bytes are +0 and 3, respectively. Integers are declared as follows: +.ie t .DS +.el .DS L +\fIInteger\fP + +\f(CW(MSB) (LSB) ++-------+-------+-------+-------+ +|byte 0 |byte 1 |byte 2 |byte 3 | ++-------+-------+-------+-------+ +<------------32 bits------------>\fP +.DE +.NH 2 +\&Unsigned Integer +.IX XDR "unsigned integer" +.IX XDR "integer, unsigned" +.LP +An XDR unsigned integer is a 32-bit datum that encodes a nonnegative +integer in the range [0,4294967295]. It is represented by an +unsigned binary number whose most and least significant bytes are 0 +and 3, respectively. An unsigned integer is declared as follows: +.ie t .DS +.el .DS L +\fIUnsigned Integer\fP + +\f(CW(MSB) (LSB) ++-------+-------+-------+-------+ +|byte 0 |byte 1 |byte 2 |byte 3 | ++-------+-------+-------+-------+ +<------------32 bits------------>\fP +.DE +.NH 2 +\&Enumeration +.IX XDR enumeration +.LP +Enumerations have the same representation as signed integers. +Enumerations are handy for describing subsets of the integers. +Enumerated data is declared as follows: +.ft CW +.DS +enum { name-identifier = constant, ... } identifier; +.DE +For example, the three colors red, yellow, and blue could be +described by an enumerated type: +.DS +.ft CW +enum { RED = 2, YELLOW = 3, BLUE = 5 } colors; +.DE +It is an error to encode as an enum any other integer than those that +have been given assignments in the enum declaration. +.NH 2 +\&Boolean +.IX XDR boolean +.LP +Booleans are important enough and occur frequently enough to warrant +their own explicit type in the standard. Booleans are declared as +follows: +.DS +.ft CW +bool identifier; +.DE +This is equivalent to: +.DS +.ft CW +enum { FALSE = 0, TRUE = 1 } identifier; +.DE +.NH 2 +\&Hyper Integer and Unsigned Hyper Integer +.IX XDR "hyper integer" +.IX XDR "integer, hyper" +.LP +The standard also defines 64-bit (8-byte) numbers called hyper +integer and unsigned hyper integer. Their representations are the +obvious extensions of integer and unsigned integer defined above. +They are represented in two's complement notation. The most and +least significant bytes are 0 and 7, respectively. Their +declarations: +.ie t .DS +.el .DS L +\fIHyper Integer\fP +\fIUnsigned Hyper Integer\fP + +\f(CW(MSB) (LSB) ++-------+-------+-------+-------+-------+-------+-------+-------+ +|byte 0 |byte 1 |byte 2 |byte 3 |byte 4 |byte 5 |byte 6 |byte 7 | ++-------+-------+-------+-------+-------+-------+-------+-------+ +<----------------------------64 bits---------------------------->\fP +.DE +.NH 2 +\&Floating-point +.IX XDR "integer, floating point" +.IX XDR "floating-point integer" +.LP +The standard defines the floating-point data type "float" (32 bits or +4 bytes). The encoding used is the IEEE standard for normalized +single-precision floating-point numbers [3]. The following three +fields describe the single-precision floating-point number: +.RS +.IP \fBS\fP: +The sign of the number. Values 0 and 1 represent positive and +negative, respectively. One bit. +.IP \fBE\fP: +The exponent of the number, base 2. 8 bits are devoted to this +field. The exponent is biased by 127. +.IP \fBF\fP: +The fractional part of the number's mantissa, base 2. 23 bits +are devoted to this field. +.RE +.LP +Therefore, the floating-point number is described by: +.DS +(-1)**S * 2**(E-Bias) * 1.F +.DE +It is declared as follows: +.ie t .DS +.el .DS L +\fISingle-Precision Floating-Point\fP + +\f(CW+-------+-------+-------+-------+ +|byte 0 |byte 1 |byte 2 |byte 3 | +S| E | F | ++-------+-------+-------+-------+ +1|<- 8 ->|<-------23 bits------>| +<------------32 bits------------>\fP +.DE +Just as the most and least significant bytes of a number are 0 and 3, +the most and least significant bits of a single-precision floating- +point number are 0 and 31. The beginning bit (and most significant +bit) offsets of S, E, and F are 0, 1, and 9, respectively. Note that +these numbers refer to the mathematical positions of the bits, and +NOT to their actual physical locations (which vary from medium to +medium). +.LP +The IEEE specifications should be consulted concerning the encoding +for signed zero, signed infinity (overflow), and denormalized numbers +(underflow) [3]. According to IEEE specifications, the "NaN" (not a +number) is system dependent and should not be used externally. +.NH 2 +\&Double-precision Floating-point +.IX XDR "integer, double-precision floating point" +.IX XDR "double-precision floating-point integer" +.LP +The standard defines the encoding for the double-precision floating- +point data type "double" (64 bits or 8 bytes). The encoding used is +the IEEE standard for normalized double-precision floating-point +numbers [3]. The standard encodes the following three fields, which +describe the double-precision floating-point number: +.RS +.IP \fBS\fP: +The sign of the number. Values 0 and 1 represent positive and +negative, respectively. One bit. +.IP \fBE\fP: +The exponent of the number, base 2. 11 bits are devoted to this +field. The exponent is biased by 1023. +.IP \fBF\fP: +The fractional part of the number's mantissa, base 2. 52 bits +are devoted to this field. +.RE +.LP +Therefore, the floating-point number is described by: +.DS +(-1)**S * 2**(E-Bias) * 1.F +.DE +It is declared as follows: +.ie t .DS +.el .DS L +\fIDouble-Precision Floating-Point\fP + +\f(CW+------+------+------+------+------+------+------+------+ +|byte 0|byte 1|byte 2|byte 3|byte 4|byte 5|byte 6|byte 7| +S| E | F | ++------+------+------+------+------+------+------+------+ +1|<--11-->|<-----------------52 bits------------------->| +<-----------------------64 bits------------------------->\fP +.DE +Just as the most and least significant bytes of a number are 0 and 3, +the most and least significant bits of a double-precision floating- +point number are 0 and 63. The beginning bit (and most significant +bit) offsets of S, E , and F are 0, 1, and 12, respectively. Note +that these numbers refer to the mathematical positions of the bits, +and NOT to their actual physical locations (which vary from medium to +medium). +.LP +The IEEE specifications should be consulted concerning the encoding +for signed zero, signed infinity (overflow), and denormalized numbers +(underflow) [3]. According to IEEE specifications, the "NaN" (not a +number) is system dependent and should not be used externally. +.NH 2 +\&Fixed-length Opaque Data +.IX XDR "fixed-length opaque data" +.IX XDR "opaque data, fixed length" +.LP +At times, fixed-length uninterpreted data needs to be passed among +machines. This data is called "opaque" and is declared as follows: +.DS +.ft CW +opaque identifier[n]; +.DE +where the constant n is the (static) number of bytes necessary to +contain the opaque data. If n is not a multiple of four, then the n +bytes are followed by enough (0 to 3) residual zero bytes, r, to make +the total byte count of the opaque object a multiple of four. +.ie t .DS +.el .DS L +\fIFixed-Length Opaque\fP + +\f(CW0 1 ... ++--------+--------+...+--------+--------+...+--------+ +| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 | ++--------+--------+...+--------+--------+...+--------+ +|<-----------n bytes---------->|<------r bytes------>| +|<-----------n+r (where (n+r) mod 4 = 0)------------>|\fP +.DE +.NH 2 +\&Variable-length Opaque Data +.IX XDR "variable-length opaque data" +.IX XDR "opaque data, variable length" +.LP +The standard also provides for variable-length (counted) opaque data, +defined as a sequence of n (numbered 0 through n-1) arbitrary bytes +to be the number n encoded as an unsigned integer (as described +below), and followed by the n bytes of the sequence. +.LP +Byte m of the sequence always precedes byte m+1 of the sequence, and +byte 0 of the sequence always follows the sequence's length (count). +enough (0 to 3) residual zero bytes, r, to make the total byte count +a multiple of four. Variable-length opaque data is declared in the +following way: +.DS +.ft CW +opaque identifier; +.DE +or +.DS +.ft CW +opaque identifier<>; +.DE +The constant m denotes an upper bound of the number of bytes that the +sequence may contain. If m is not specified, as in the second +declaration, it is assumed to be (2**32) - 1, the maximum length. +The constant m would normally be found in a protocol specification. +For example, a filing protocol may state that the maximum data +transfer size is 8192 bytes, as follows: +.DS +.ft CW +opaque filedata<8192>; +.DE +This can be illustrated as follows: +.ie t .DS +.el .DS L +\fIVariable-Length Opaque\fP + +\f(CW0 1 2 3 4 5 ... ++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ +| length n |byte0|byte1|...| n-1 | 0 |...| 0 | ++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ +|<-------4 bytes------->|<------n bytes------>|<---r bytes--->| +|<----n+r (where (n+r) mod 4 = 0)---->|\fP +.DE +.LP +It is an error to encode a length greater than the maximum +described in the specification. +.NH 2 +\&String +.IX XDR string +.LP +The standard defines a string of n (numbered 0 through n-1) ASCII +bytes to be the number n encoded as an unsigned integer (as described +above), and followed by the n bytes of the string. Byte m of the +string always precedes byte m+1 of the string, and byte 0 of the +string always follows the string's length. If n is not a multiple of +four, then the n bytes are followed by enough (0 to 3) residual zero +bytes, r, to make the total byte count a multiple of four. Counted +byte strings are declared as follows: +.DS +.ft CW +string object; +.DE +or +.DS +.ft CW +string object<>; +.DE +The constant m denotes an upper bound of the number of bytes that a +string may contain. If m is not specified, as in the second +declaration, it is assumed to be (2**32) - 1, the maximum length. +The constant m would normally be found in a protocol specification. +For example, a filing protocol may state that a file name can be no +longer than 255 bytes, as follows: +.DS +.ft CW +string filename<255>; +.DE +Which can be illustrated as: +.ie t .DS +.el .DS L +\fIA String\fP + +\f(CW0 1 2 3 4 5 ... ++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ +| length n |byte0|byte1|...| n-1 | 0 |...| 0 | ++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ +|<-------4 bytes------->|<------n bytes------>|<---r bytes--->| +|<----n+r (where (n+r) mod 4 = 0)---->|\fP +.DE +.LP +It is an error to encode a length greater than the maximum +described in the specification. +.NH 2 +\&Fixed-length Array +.IX XDR "fixed-length array" +.IX XDR "array, fixed length" +.LP +Declarations for fixed-length arrays of homogeneous elements are in +the following form: +.DS +.ft CW +type-name identifier[n]; +.DE +Fixed-length arrays of elements numbered 0 through n-1 are encoded by +individually encoding the elements of the array in their natural +order, 0 through n-1. Each element's size is a multiple of four +bytes. Though all elements are of the same type, the elements may +have different sizes. For example, in a fixed-length array of +strings, all elements are of type "string", yet each element will +vary in its length. +.ie t .DS +.el .DS L +\fIFixed-Length Array\fP + +\f(CW+---+---+---+---+---+---+---+---+...+---+---+---+---+ +| element 0 | element 1 |...| element n-1 | ++---+---+---+---+---+---+---+---+...+---+---+---+---+ +|<--------------------n elements------------------->|\fP +.DE +.NH 2 +\&Variable-length Array +.IX XDR "variable-length array" +.IX XDR "array, variable length" +.LP +Counted arrays provide the ability to encode variable-length arrays +of homogeneous elements. The array is encoded as the element count n +(an unsigned integer) followed by the encoding of each of the array's +elements, starting with element 0 and progressing through element n- +1. The declaration for variable-length arrays follows this form: +.DS +.ft CW +type-name identifier; +.DE +or +.DS +.ft CW +type-name identifier<>; +.DE +The constant m specifies the maximum acceptable element count of an +array; if m is not specified, as in the second declaration, it is +assumed to be (2**32) - 1. +.ie t .DS +.el .DS L +\fICounted Array\fP + +\f(CW0 1 2 3 ++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+ +| n | element 0 | element 1 |...|element n-1| ++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+ +|<-4 bytes->|<--------------n elements------------->|\fP +.DE +It is an error to encode a value of n that is greater than the +maximum described in the specification. +.NH 2 +\&Structure +.IX XDR structure +.LP +Structures are declared as follows: +.DS +.ft CW +struct { + component-declaration-A; + component-declaration-B; + \&... +} identifier; +.DE +The components of the structure are encoded in the order of their +declaration in the structure. Each component's size is a multiple of +four bytes, though the components may be different sizes. +.ie t .DS +.el .DS L +\fIStructure\fP + +\f(CW+-------------+-------------+... +| component A | component B |... ++-------------+-------------+...\fP +.DE +.NH 2 +\&Discriminated Union +.IX XDR "discriminated union" +.IX XDR union discriminated +.LP +A discriminated union is a type composed of a discriminant followed +by a type selected from a set of prearranged types according to the +value of the discriminant. The type of discriminant is either "int", +"unsigned int", or an enumerated type, such as "bool". The component +types are called "arms" of the union, and are preceded by the value +of the discriminant which implies their encoding. Discriminated +unions are declared as follows: +.DS +.ft CW +union switch (discriminant-declaration) { + case discriminant-value-A: + arm-declaration-A; + case discriminant-value-B: + arm-declaration-B; + \&... + default: default-declaration; +} identifier; +.DE +Each "case" keyword is followed by a legal value of the discriminant. +The default arm is optional. If it is not specified, then a valid +encoding of the union cannot take on unspecified discriminant values. +The size of the implied arm is always a multiple of four bytes. +.LP +The discriminated union is encoded as its discriminant followed by +the encoding of the implied arm. +.ie t .DS +.el .DS L +\fIDiscriminated Union\fP + +\f(CW0 1 2 3 ++---+---+---+---+---+---+---+---+ +| discriminant | implied arm | ++---+---+---+---+---+---+---+---+ +|<---4 bytes--->|\fP +.DE +.NH 2 +\&Void +.IX XDR void +.LP +An XDR void is a 0-byte quantity. Voids are useful for describing +operations that take no data as input or no data as output. They are +also useful in unions, where some arms may contain data and others do +not. The declaration is simply as follows: +.DS +.ft CW +void; +.DE +Voids are illustrated as follows: +.ie t .DS +.el .DS L +\fIVoid\fP + +\f(CW ++ + || + ++ +--><-- 0 bytes\fP +.DE +.NH 2 +\&Constant +.IX XDR constant +.LP +The data declaration for a constant follows this form: +.DS +.ft CW +const name-identifier = n; +.DE +"const" is used to define a symbolic name for a constant; it does not +declare any data. The symbolic constant may be used anywhere a +regular constant may be used. For example, the following defines a +symbolic constant DOZEN, equal to 12. +.DS +.ft CW +const DOZEN = 12; +.DE +.NH 2 +\&Typedef +.IX XDR typedef +.LP +"typedef" does not declare any data either, but serves to define new +identifiers for declaring data. The syntax is: +.DS +.ft CW +typedef declaration; +.DE +The new type name is actually the variable name in the declaration +part of the typedef. For example, the following defines a new type +called "eggbox" using an existing type called "egg": +.DS +.ft CW +typedef egg eggbox[DOZEN]; +.DE +Variables declared using the new type name have the same type as the +new type name would have in the typedef, if it was considered a +variable. For example, the following two declarations are equivalent +in declaring the variable "fresheggs": +.DS +.ft CW +eggbox fresheggs; +egg fresheggs[DOZEN]; +.DE +When a typedef involves a struct, enum, or union definition, there is +another (preferred) syntax that may be used to define the same type. +In general, a typedef of the following form: +.DS +.ft CW +typedef <> identifier; +.DE +may be converted to the alternative form by removing the "typedef" +part and placing the identifier after the "struct", "union", or +"enum" keyword, instead of at the end. For example, here are the two +ways to define the type "bool": +.DS +.ft CW +typedef enum { /* \fIusing typedef\fP */ + FALSE = 0, + TRUE = 1 + } bool; + +enum bool { /* \fIpreferred alternative\fP */ + FALSE = 0, + TRUE = 1 + }; +.DE +The reason this syntax is preferred is one does not have to wait +until the end of a declaration to figure out the name of the new +type. +.NH 2 +\&Optional-data +.IX XDR "optional data" +.IX XDR "data, optional" +.LP +Optional-data is one kind of union that occurs so frequently that we +give it a special syntax of its own for declaring it. It is declared +as follows: +.DS +.ft CW +type-name *identifier; +.DE +This is equivalent to the following union: +.DS +.ft CW +union switch (bool opted) { + case TRUE: + type-name element; + case FALSE: + void; +} identifier; +.DE +It is also equivalent to the following variable-length array +declaration, since the boolean "opted" can be interpreted as the +length of the array: +.DS +.ft CW +type-name identifier<1>; +.DE +Optional-data is not so interesting in itself, but it is very useful +for describing recursive data-structures such as linked-lists and +trees. For example, the following defines a type "stringlist" that +encodes lists of arbitrary length strings: +.DS +.ft CW +struct *stringlist { + string item<>; + stringlist next; +}; +.DE +It could have been equivalently declared as the following union: +.DS +.ft CW +union stringlist switch (bool opted) { + case TRUE: + struct { + string item<>; + stringlist next; + } element; + case FALSE: + void; +}; +.DE +or as a variable-length array: +.DS +.ft CW +struct stringlist<1> { + string item<>; + stringlist next; +}; +.DE +Both of these declarations obscure the intention of the stringlist +type, so the optional-data declaration is preferred over both of +them. The optional-data type also has a close correlation to how +recursive data structures are represented in high-level languages +such as Pascal or C by use of pointers. In fact, the syntax is the +same as that of the C language for pointers. +.NH 2 +\&Areas for Future Enhancement +.IX XDR futures +.LP +The XDR standard lacks representations for bit fields and bitmaps, +since the standard is based on bytes. Also missing are packed (or +binary-coded) decimals. +.LP +The intent of the XDR standard was not to describe every kind of data +that people have ever sent or will ever want to send from machine to +machine. Rather, it only describes the most commonly used data-types +of high-level languages such as Pascal or C so that applications +written in these languages will be able to communicate easily over +some medium. +.LP +One could imagine extensions to XDR that would let it describe almost +any existing protocol, such as TCP. The minimum necessary for this +are support for different block sizes and byte-orders. The XDR +discussed here could then be considered the 4-byte big-endian member +of a larger XDR family. +.NH 1 +\&Discussion +.sp 2 +.NH 2 +\&Why a Language for Describing Data? +.IX XDR language +.LP +There are many advantages in using a data-description language such +as XDR versus using diagrams. Languages are more formal than +diagrams and lead to less ambiguous descriptions of data. +Languages are also easier to understand and allow one to think of +other issues instead of the low-level details of bit-encoding. +Also, there is a close analogy between the types of XDR and a +high-level language such as C or Pascal. This makes the +implementation of XDR encoding and decoding modules an easier task. +Finally, the language specification itself is an ASCII string that +can be passed from machine to machine to perform on-the-fly data +interpretation. +.NH 2 +\&Why Only one Byte-Order for an XDR Unit? +.IX XDR "byte order" +.LP +Supporting two byte-orderings requires a higher level protocol for +determining in which byte-order the data is encoded. Since XDR is +not a protocol, this can't be done. The advantage of this, though, +is that data in XDR format can be written to a magnetic tape, for +example, and any machine will be able to interpret it, since no +higher level protocol is necessary for determining the byte-order. +.NH 2 +\&Why does XDR use Big-Endian Byte-Order? +.LP +Yes, it is unfair, but having only one byte-order means you have to +be unfair to somebody. Many architectures, such as the Motorola +68000 and IBM 370, support the big-endian byte-order. +.NH 2 +\&Why is the XDR Unit Four Bytes Wide? +.LP +There is a tradeoff in choosing the XDR unit size. Choosing a small +size such as two makes the encoded data small, but causes alignment +problems for machines that aren't aligned on these boundaries. A +large size such as eight means the data will be aligned on virtually +every machine, but causes the encoded data to grow too big. We chose +four as a compromise. Four is big enough to support most +architectures efficiently, except for rare machines such as the +eight-byte aligned Cray. Four is also small enough to keep the +encoded data restricted to a reasonable size. +.NH 2 +\&Why must Variable-Length Data be Padded with Zeros? +.IX XDR "variable-length data" +.LP +It is desirable that the same data encode into the same thing on all +machines, so that encoded data can be meaningfully compared or +checksummed. Forcing the padded bytes to be zero ensures this. +.NH 2 +\&Why is there No Explicit Data-Typing? +.LP +Data-typing has a relatively high cost for what small advantages it +may have. One cost is the expansion of data due to the inserted type +fields. Another is the added cost of interpreting these type fields +and acting accordingly. And most protocols already know what type +they expect, so data-typing supplies only redundant information. +However, one can still get the benefits of data-typing using XDR. One +way is to encode two things: first a string which is the XDR data +description of the encoded data, and then the encoded data itself. +Another way is to assign a value to all the types in XDR, and then +define a universal type which takes this value as its discriminant +and for each value, describes the corresponding data type. +.NH 1 +\&The XDR Language Specification +.IX XDR language +.sp 1 +.NH 2 +\&Notational Conventions +.IX "XDR language" notation +.LP +This specification uses an extended Backus-Naur Form notation for +describing the XDR language. Here is a brief description of the +notation: +.IP 1. +The characters +.I | , +.I ( , +.I ) , +.I [ , +.I ] , +.I " , +and +.I * +are special. +.IP 2. +Terminal symbols are strings of any characters surrounded by +double quotes. +.IP 3. +Non-terminal symbols are strings of non-special characters. +.IP 4. +Alternative items are separated by a vertical bar ("\fI|\fP"). +.IP 5. +Optional items are enclosed in brackets. +.IP 6. +Items are grouped together by enclosing them in parentheses. +.IP 7. +A +.I * +following an item means 0 or more occurrences of that item. +.LP +For example, consider the following pattern: +.DS L +"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night") +.DE +.LP +An infinite number of strings match this pattern. A few of them +are: +.DS +"a very rainy day" +"a very, very rainy day" +"a very cold and rainy day" +"a very, very, very cold and rainy night" +.DE +.NH 2 +\&Lexical Notes +.IP 1. +Comments begin with '/*' and terminate with '*/'. +.IP 2. +White space serves to separate items and is otherwise ignored. +.IP 3. +An identifier is a letter followed by an optional sequence of +letters, digits or underbar ('_'). The case of identifiers is +not ignored. +.IP 4. +A constant is a sequence of one or more decimal digits, +optionally preceded by a minus-sign ('-'). +.NH 2 +\&Syntax Information +.IX "XDR language" syntax +.DS +.ft CW +declaration: + type-specifier identifier + | type-specifier identifier "[" value "]" + | type-specifier identifier "<" [ value ] ">" + | "opaque" identifier "[" value "]" + | "opaque" identifier "<" [ value ] ">" + | "string" identifier "<" [ value ] ">" + | type-specifier "*" identifier + | "void" +.DE +.DS +.ft CW +value: + constant + | identifier + +type-specifier: + [ "unsigned" ] "int" + | [ "unsigned" ] "hyper" + | "float" + | "double" + | "bool" + | enum-type-spec + | struct-type-spec + | union-type-spec + | identifier +.DE +.DS +.ft CW +enum-type-spec: + "enum" enum-body + +enum-body: + "{" + ( identifier "=" value ) + ( "," identifier "=" value )* + "}" +.DE +.DS +.ft CW +struct-type-spec: + "struct" struct-body + +struct-body: + "{" + ( declaration ";" ) + ( declaration ";" )* + "}" +.DE +.DS +.ft CW +union-type-spec: + "union" union-body + +union-body: + "switch" "(" declaration ")" "{" + ( "case" value ":" declaration ";" ) + ( "case" value ":" declaration ";" )* + [ "default" ":" declaration ";" ] + "}" + +constant-def: + "const" identifier "=" constant ";" +.DE +.DS +.ft CW +type-def: + "typedef" declaration ";" + | "enum" identifier enum-body ";" + | "struct" identifier struct-body ";" + | "union" identifier union-body ";" + +definition: + type-def + | constant-def + +specification: + definition * +.DE +.NH 3 +\&Syntax Notes +.IX "XDR language" syntax +.LP +.IP 1. +The following are keywords and cannot be used as identifiers: +"bool", "case", "const", "default", "double", "enum", "float", +"hyper", "opaque", "string", "struct", "switch", "typedef", "union", +"unsigned" and "void". +.IP 2. +Only unsigned constants may be used as size specifications for +arrays. If an identifier is used, it must have been declared +previously as an unsigned constant in a "const" definition. +.IP 3. +Constant and type identifiers within the scope of a specification +are in the same name space and must be declared uniquely within this +scope. +.IP 4. +Similarly, variable names must be unique within the scope of +struct and union declarations. Nested struct and union declarations +create new scopes. +.IP 5. +The discriminant of a union must be of a type that evaluates to +an integer. That is, "int", "unsigned int", "bool", an enumerated +type or any typedefed type that evaluates to one of these is legal. +Also, the case values must be one of the legal values of the +discriminant. Finally, a case value may not be specified more than +once within the scope of a union declaration. +.NH 1 +\&An Example of an XDR Data Description +.LP +Here is a short XDR data description of a thing called a "file", +which might be used to transfer files from one machine to another. +.ie t .DS +.el .DS L +.ft CW + +const MAXUSERNAME = 32; /*\fI max length of a user name \fP*/ +const MAXFILELEN = 65535; /*\fI max length of a file \fP*/ +const MAXNAMELEN = 255; /*\fI max length of a file name \fP*/ + +.ft I +/* + * Types of files: + */ +.ft CW + +enum filekind { + TEXT = 0, /*\fI ascii data \fP*/ + DATA = 1, /*\fI raw data \fP*/ + EXEC = 2 /*\fI executable \fP*/ +}; + +.ft I +/* + * File information, per kind of file: + */ +.ft CW + +union filetype switch (filekind kind) { + case TEXT: + void; /*\fI no extra information \fP*/ + case DATA: + string creator; /*\fI data creator \fP*/ + case EXEC: + string interpretor; /*\fI program interpretor \fP*/ +}; + +.ft I +/* + * A complete file: + */ +.ft CW + +struct file { + string filename; /*\fI name of file \fP*/ + filetype type; /*\fI info about file \fP*/ + string owner; /*\fI owner of file \fP*/ + opaque data; /*\fI file data \fP*/ +}; +.DE +.LP +Suppose now that there is a user named "john" who wants to store +his lisp program "sillyprog" that contains just the data "(quit)". +His file would be encoded as follows: +.TS +box tab (&) ; +lfI lfI lfI lfI +rfL rfL rfL l . +Offset&Hex Bytes&ASCII&Description +_ +0&00 00 00 09&....&Length of filename = 9 +4&73 69 6c 6c&sill&Filename characters +8&79 70 72 6f&ypro& ... and more characters ... +12&67 00 00 00&g...& ... and 3 zero-bytes of fill +16&00 00 00 02&....&Filekind is EXEC = 2 +20&00 00 00 04&....&Length of interpretor = 4 +24&6c 69 73 70&lisp&Interpretor characters +28&00 00 00 04&....&Length of owner = 4 +32&6a 6f 68 6e&john&Owner characters +36&00 00 00 06&....&Length of file data = 6 +40&28 71 75 69&(qui&File data bytes ... +44&74 29 00 00&t)..& ... and 2 zero-bytes of fill +.TE +.NH 1 +\&References +.LP +[1] Brian W. Kernighan & Dennis M. Ritchie, "The C Programming +Language", Bell Laboratories, Murray Hill, New Jersey, 1978. +.LP +[2] Danny Cohen, "On Holy Wars and a Plea for Peace", IEEE Computer, +October 1981. +.LP +[3] "IEEE Standard for Binary Floating-Point Arithmetic", ANSI/IEEE +Standard 754-1985, Institute of Electrical and Electronics +Engineers, August 1985. +.LP +[4] "Courier: The Remote Procedure Call Protocol", XEROX +Corporation, XSIS 038112, December 1981. diff --git a/c/src/exec/librpc/src/rpc/README b/c/src/exec/librpc/src/rpc/README index e69de29bb2..ad9d70f990 100644 --- a/c/src/exec/librpc/src/rpc/README +++ b/c/src/exec/librpc/src/rpc/README @@ -0,0 +1,233 @@ +RPCSRC 4.0 7/11/89 + +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: + +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.) + +If you wish to report bugs found in this release, send mail to: + +Portable ONC/NFS +Sun Microsystems, Inc +MS 12-33 +2550 Garcia Avenue +Mountain View, CA 94043 + +or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet). + +ROADMAP + +The directory hierarchy is as follows: + + 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. + + man/ Manual pages for RPC library, rpcgen, and utilities. + + rpc/ The RPC and XDR library. SEE BELOW + FOR BUGFIX TO 4.2BSD COMPILER. + + rpcgen/ The RPC Language compiler (for .x files) + + rpcsvc/ Service definition files for various services and the + server and client code for the Remote Status service. + + 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. + +BUILD INSTRUCTIONS + +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. +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 +(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 +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". diff --git a/c/src/exec/librpc/src/rpc/auth_des.c b/c/src/exec/librpc/src/rpc/auth_des.c index e69de29bb2..87d55b67e7 100644 --- a/c/src/exec/librpc/src/rpc/auth_des.c +++ b/c/src/exec/librpc/src/rpc/auth_des.c @@ -0,0 +1,554 @@ +/* + * 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. + */ +/* + * auth_des.c, client-side implementation of DES authentication + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* XXX: just to get htonl() and ntohl() */ +#include +#undef NIS +#include + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */ +static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/auth_des.c,v 1.3 1999/08/28 00:00:32 peter Exp $"; +#endif + +extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *, + char *, char **, struct sockaddr_in * )); +extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *)); +extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * )); +extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * )); + +#define MILLION 1000000L +#define RTIME_TIMEOUT 5 /* seconds to wait for sync */ + +#define 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) */ + +/* + * DES authenticator operations vector + */ +static void authdes_nextverf(); +static bool_t authdes_marshal(); +static bool_t authdes_validate(); +static bool_t authdes_refresh(); +static void authdes_destroy(); +static struct auth_ops authdes_ops = { + authdes_nextverf, + authdes_marshal, + authdes_validate, + authdes_refresh, + authdes_destroy +}; +#ifdef foo +static bool_t synchronize __P(( struct sockaddr *, struct timeval *)); +#endif +/* + * This struct is pointed to by the ah_private field of an "AUTH *" + */ +struct ad_private { + char *ad_fullname; /* client's full name */ + u_int ad_fullnamelen; /* length of name, rounded up */ + char *ad_servername; /* server's full name */ + u_int ad_servernamelen; /* length of name, rounded up */ + u_int ad_window; /* client specified window */ + bool_t ad_dosync; /* synchronize? */ + struct sockaddr 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 */ + struct authdes_cred ad_cred; /* storage for credential */ + struct authdes_verf ad_verf; /* storage for verifier */ + struct timeval ad_timestamp; /* timestamp sent */ + des_block ad_xkey; /* encrypted conversation key */ + u_char ad_pkey[1024]; /* Server's actual public key */ + char *ad_netid; /* Timehost netid */ + char *ad_uaddr; /* Timehost uaddr */ + nis_server *ad_nis_srvr; /* NIS+ server struct */ +}; + + +/* + * Create the client des authentication object + */ +AUTH * +authdes_create(servername, window, syncaddr, ckey) + char *servername; /* network name of server */ + u_int window; /* time to live */ + struct sockaddr *syncaddr; /* optional addr of host to sync with */ + des_block *ckey; /* optional conversation key to use*/ +{ + + AUTH *auth; + struct ad_private *ad; + char namebuf[MAXNETNAMELEN+1]; + u_char pkey_data[1024]; + + if (!getpublickey(servername, pkey_data)) + return(NULL); + + /* + * Allocate everything now + */ + auth = ALLOC(AUTH); + ad = ALLOC(struct ad_private); + (void) getnetname(namebuf); + + ad->ad_fullnamelen = RNDUP(strlen(namebuf)); + ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); + + ad->ad_servernamelen = strlen(servername); + ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); + + if (auth == NULL || ad == NULL || ad->ad_fullname == NULL || + ad->ad_servername == NULL) { + debug("authdes_create: out of memory"); + goto failed; + } + + /* + * Set up private data + */ + bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1); + bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1); + bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1); + if (syncaddr != NULL) { + ad->ad_syncaddr = *syncaddr; + ad->ad_dosync = TRUE; + } else { + ad->ad_dosync = FALSE; + } + ad->ad_window = window; + if (ckey == NULL) { + if (key_gendes(&auth->ah_key) < 0) { + debug("authdes_create: unable to gen conversation key"); + return (NULL); + } + } else { + auth->ah_key = *ckey; + } + + /* + * 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); +} + +/* + * Slightly modified version of authdes_create which takes the public key + * of the server principal as an argument. This spares us a call to + * getpublickey() which in the nameserver context can cause a deadlock. + */ +AUTH * +authdes_pk_create(servername, pkey, window, timehost, ckey, srvr) + char *servername; /* network name of server */ + netobj *pkey; /* public key of server */ + u_int window; /* time to live */ + char *timehost; /* optional hostname to sync with */ + des_block *ckey; /* optional conversation key to use */ + nis_server *srvr; /* optional NIS+ server struct */ +{ + AUTH *auth; + struct ad_private *ad; + char namebuf[MAXNETNAMELEN+1]; + + /* + * Allocate everything now + */ + auth = ALLOC(AUTH); + if (auth == NULL) { + debug("authdes_pk_create: out of memory"); + return (NULL); + } + ad = ALLOC(struct ad_private); + if (ad == NULL) { + debug("authdes_pk_create: out of memory"); + goto failed; + } + ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ + ad->ad_timehost = NULL; + ad->ad_netid = NULL; + ad->ad_uaddr = NULL; + ad->ad_nis_srvr = NULL; + ad->ad_timediff.tv_sec = 0; + ad->ad_timediff.tv_usec = 0; + memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); + if (!getnetname(namebuf)) + goto failed; + ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); + ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); + ad->ad_servernamelen = strlen(servername); + ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); + + if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { + debug("authdes_pk_create: 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"); + goto failed; + } + memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); + ad->ad_dosync = TRUE; + } else if (srvr != NULL) { + ad->ad_nis_srvr = srvr; /* transient */ + ad->ad_dosync = TRUE; + } else { + ad->ad_dosync = FALSE; + } + memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); + memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); + ad->ad_window = window; + if (ckey == NULL) { + if (key_gendes(&auth->ah_key) < 0) { + debug("authdes_pk_create: unable to gen conversation key"); + goto failed; + } + } else { + auth->ah_key = *ckey; + } + + /* + * Set up auth handle + */ + auth->ah_cred.oa_flavor = AUTH_DES; + auth->ah_verf.oa_flavor = AUTH_DES; + auth->ah_ops = &authdes_ops; + auth->ah_private = (caddr_t)ad; + + if (!authdes_refresh(auth)) { + goto failed; + } + ad->ad_nis_srvr = NULL; /* not needed any longer */ + return (auth); + +failed: + if (auth) + FREE(auth, sizeof (AUTH)); + if (ad) { + if (ad->ad_fullname) + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + if (ad->ad_servername) + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + if (ad->ad_timehost) + FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); + if (ad->ad_netid) + free(ad->ad_netid); + if (ad->ad_uaddr) + free(ad->ad_uaddr); + FREE(ad, sizeof (struct ad_private)); + } + return (NULL); +} +/* + * Implement the five authentication operations + */ + + +/* + * 1. Next Verifier + */ +/*ARGSUSED*/ +static void +authdes_nextverf(auth) + AUTH *auth; +{ + /* what the heck am I supposed to do??? */ +} + + + +/* + * 2. Marshal + */ +static bool_t +authdes_marshal(auth, xdrs) + AUTH *auth; + XDR *xdrs; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + struct authdes_verf *verf = &ad->ad_verf; + des_block cryptbuf[2]; + des_block ivec; + int status; + long len; + int32_t *ixdr; + + /* + * Figure out the "time", accounting for any time difference + * with the server if necessary. + */ + (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL); + ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; + ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; + if (ad->ad_timestamp.tv_usec >= MILLION) { + ad->ad_timestamp.tv_usec -= MILLION; + ad->ad_timestamp.tv_sec += 1; + } + + /* + * 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); + 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); + 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); + } else { + status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + } + if (DES_FAILED(status)) { + debug("authdes_marshal: DES encryption failure"); + return (FALSE); + } + ad->ad_verf.adv_xtimestamp = cryptbuf[0]; + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; + ad->ad_verf.adv_winverf = cryptbuf[1].key.low; + } else { + ad->ad_cred.adc_nickname = ad->ad_nickname; + ad->ad_verf.adv_winverf = 0; + } + + /* + * Serialize the credential and verifier into opaque + * authentication data. + */ + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); + } else { + len = (1 + 1)*BYTES_PER_XDR_UNIT; + } + + if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { + IXDR_PUT_LONG(ixdr, AUTH_DES); + IXDR_PUT_LONG(ixdr, len); + } else { + ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor)); + ATTEMPT(xdr_putlong(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); + } else { + ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor)); + ATTEMPT(xdr_putlong(xdrs, &len)); + } + ATTEMPT(xdr_authdes_verf(xdrs, verf)); + return (TRUE); +} + + +/* + * 3. Validate + */ +static bool_t +authdes_validate(auth, rverf) + AUTH *auth; + struct opaque_auth *rverf; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_verf verf; + int status; + register u_long *ixdr; + + 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 ! */ + + /* + * Decrypt the timestamp + */ + status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp, + sizeof(des_block), DES_DECRYPT | DES_HW); + + if (DES_FAILED(status)) { + debug("authdes_validate: DES decryption failure"); + return (FALSE); + } + + /* + * 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); + + /* + * validate + */ + if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, + sizeof(struct timeval)) != 0) { + debug("authdes_validate: verifier mismatch\n"); + return (FALSE); + } + + /* + * We have a nickname now, let's use it + */ + ad->ad_nickname = verf.adv_nickname; + ad->ad_cred.adc_namekind = ADN_NICKNAME; + return (TRUE); +} + +/* + * 4. Refresh + */ +static bool_t +authdes_refresh(auth) + AUTH *auth; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + 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"); + } + ad->ad_xkey = auth->ah_key; + pkey.n_bytes = (char *)(ad->ad_pkey); + pkey.n_len = 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"); + return (FALSE); + } + cred->adc_fullname.key = ad->ad_xkey; + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = ad->ad_fullname; + return (TRUE); +} + + +/* + * 5. Destroy + */ +static void +authdes_destroy(auth) + AUTH *auth; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + FREE(ad, sizeof(struct ad_private)); + FREE(auth, sizeof(AUTH)); +} + + +#ifdef old +/* + * Synchronize with the server at the given address, that is, + * adjust timep to reflect the delta between our clocks + */ +static bool_t +synchronize(syncaddr, timep) + struct sockaddr *syncaddr; + struct timeval *timep; +{ + struct timeval mytime; + struct timeval timeout; + + timeout.tv_sec = RTIME_TIMEOUT; + timeout.tv_usec = 0; + if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) { + return (FALSE); + } + (void) gettimeofday(&mytime, (struct timezone *)NULL); + timep->tv_sec -= mytime.tv_sec; + if (mytime.tv_usec > timep->tv_usec) { + timep->tv_sec -= 1; + timep->tv_usec += MILLION; + } + timep->tv_usec -= mytime.tv_usec; + return (TRUE); +} +#endif diff --git a/c/src/exec/librpc/src/rpc/auth_none.c b/c/src/exec/librpc/src/rpc/auth_none.c index e69de29bb2..9b08699ea8 100644 --- a/c/src/exec/librpc/src/rpc/auth_none.c +++ b/c/src/exec/librpc/src/rpc/auth_none.c @@ -0,0 +1,136 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.9 1999/08/28 00:00:32 peter Exp $"; +#endif + +/* + * auth_none.c + * Creates a client authentication handle for passing "null" + * credentials and verifiers to remote systems. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#define MAX_MARSHEL_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 struct authnone_private { + AUTH no_client; + char marshalled_client[MAX_MARSHEL_SIZE]; + u_int mcnt; +} *authnone_private; + +AUTH * +authnone_create() +{ + register struct authnone_private *ap = authnone_private; + XDR xdr_stream; + register XDR *xdrs; + + if (ap == 0) { + ap = (struct authnone_private *)calloc(1, sizeof (*ap)); + if (ap == 0) + 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; + xdrs = &xdr_stream; + xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_SIZE, + XDR_ENCODE); + (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); + (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS(xdrs); + XDR_DESTROY(xdrs); + } + return (&ap->no_client); +} + +/*ARGSUSED*/ +static bool_t +authnone_marshal(client, xdrs) + AUTH *client; + XDR *xdrs; +{ + register struct authnone_private *ap = authnone_private; + + if (ap == 0) + return (0); + return ((*xdrs->x_ops->x_putbytes)(xdrs, + ap->marshalled_client, ap->mcnt)); +} + +static void +authnone_verf() +{ +} + +static bool_t +authnone_validate() +{ + + return (TRUE); +} + +static bool_t +authnone_refresh() +{ + + return (FALSE); +} + +static void +authnone_destroy() +{ +} diff --git a/c/src/exec/librpc/src/rpc/auth_time.c b/c/src/exec/librpc/src/rpc/auth_time.c index e69de29bb2..733080a397 100644 --- a/c/src/exec/librpc/src/rpc/auth_time.c +++ b/c/src/exec/librpc/src/rpc/auth_time.c @@ -0,0 +1,503 @@ +#pragma ident "@(#)auth_time.c 1.4 92/11/10 SMI" + +/* + * auth_time.c + * + * This module contains the private function __rpc_get_time_offset() + * which will return the difference in seconds between the local system's + * notion of time and a remote server's notion of time. This must be + * possible without calling any functions that may invoke the name + * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the + * synchronize call of the authdes code to synchronize clocks between + * NIS+ clients and their servers. + * + * Note to minimize the amount of duplicate code, portions of the + * synchronize() function were folded into this code, and the synchronize + * call becomes simply a wrapper around this function. Further, if this + * function is called with a timehost it *DOES* recurse to the name + * server so don't use it in that mode if you are doing name service code. + * + * Copyright (c) 1992 Sun Microsystems Inc. + * All rights reserved. + * + * Side effects : + * When called a client handle to a RPCBIND process is created + * and destroyed. Two strings "netid" and "uaddr" are malloc'd + * and returned. The SIGALRM processing is modified only if + * needed to deal with TCP connections. + * + * 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 $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef NIS +#include + +/* + * FreeBSD currently uses RPC 4.0, which uses portmap rather than + * rpcbind. Consequently, we need to fake up these values here. + * Luckily, the RPCB_GETTIME procedure uses only base XDR data types + * so we don't need anything besides these magic numbers. + */ +#define RPCBPROG (u_long)100000 +#define RPCBVERS (u_long)3 +#define RPCBPROC_GETTIME (u_long)6 + +#ifdef TESTING +#define msg(x) printf("ERROR: %s\n", x) +/* #define msg(x) syslog(LOG_ERR, "%s", x) */ +#else +#define msg(x) +#endif + +static int saw_alarm = 0; + +static void +alarm_hndler(s) + int s; +{ + saw_alarm = 1; + return; +} + +/* + * The internet time server defines the epoch to be Jan 1, 1900 + * whereas UNIX defines it to be Jan 1, 1970. To adjust the result + * from internet time-service time, into UNIX time we subtract the + * following offset : + */ +#define NYEARS (1970 - 1900) +#define TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4))) + + +/* + * Stolen from rpc.nisd: + * Turn a 'universal address' into a struct sockaddr_in. + * Bletch. + */ +static int uaddr_to_sockaddr(uaddr, sin) +#ifdef foo + endpoint *endpt; +#endif + char *uaddr; + struct sockaddr_in *sin; +{ + unsigned char p_bytes[2]; + int i; + unsigned long a[6]; + + i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], + &a[3], &a[4], &a[5]); + + if (i < 6) + return(1); + + for (i = 0; i < 4; i++) + sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i); + + p_bytes[0] = (unsigned char)a[4] & 0x000000FF; + p_bytes[1] = (unsigned char)a[5] & 0x000000FF; + + sin->sin_family = AF_INET; /* always */ + bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2); + + return (0); +} + +/* + * free_eps() + * + * Free the strings that were strduped into the eps structure. + */ +static void +free_eps(eps, num) + endpoint eps[]; + int num; +{ + int i; + + for (i = 0; i < num; i++) { + free(eps[i].uaddr); + free(eps[i].proto); + free(eps[i].family); + } + return; +} + +/* + * get_server() + * + * This function constructs a nis_server structure description for the + * indicated hostname. + * + * NOTE: There is a chance we may end up recursing here due to the + * fact that gethostbyname() could do an NIS search. Ideally, the + * NIS+ server will call __rpc_get_time_offset() with the nis_server + * structure already populated. + */ +static nis_server * +get_server(sin, host, srv, eps, maxep) + struct sockaddr_in *sin; + char *host; /* name of the time host */ + nis_server *srv; /* nis_server struct to use. */ + endpoint eps[]; /* array of endpoints */ + int maxep; /* max array size */ +{ + char hname[256]; + int num_ep = 0, i; + struct hostent *he; + struct hostent dummy; + char *ptr[2]; + + if (host == NULL && sin == NULL) + return (NULL); + + if (sin == NULL) { + he = gethostbyname(host); + if (he == NULL) + return(NULL); + } else { + he = &dummy; + ptr[0] = (char *)&sin->sin_addr.s_addr; + ptr[1] = NULL; + dummy.h_addr_list = ptr; + } + + /* + * This is lame. We go around once for TCP, then again + * for UDP. + */ + for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); + i++, num_ep++) { + struct in_addr *a; + + a = (struct in_addr *)he->h_addr_list[i]; + snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); + eps[num_ep].uaddr = strdup(hname); + eps[num_ep].family = strdup("inet"); + eps[num_ep].proto = strdup("tcp"); + } + + for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); + i++, num_ep++) { + struct in_addr *a; + + a = (struct in_addr *)he->h_addr_list[i]; + snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); + eps[num_ep].uaddr = strdup(hname); + eps[num_ep].family = strdup("inet"); + eps[num_ep].proto = strdup("udp"); + } + + srv->name = (nis_name) host; + srv->ep.ep_len = num_ep; + srv->ep.ep_val = eps; + srv->key_type = NIS_PK_NONE; + srv->pkey.n_bytes = NULL; + srv->pkey.n_len = 0; + return (srv); +} + +/* + * __rpc_get_time_offset() + * + * This function uses a nis_server structure to contact the a remote + * machine (as named in that structure) and returns the offset in time + * between that machine and this one. This offset is returned in seconds + * and may be positive or negative. + * + * The first time through, a lot of fiddling is done with the netconfig + * stuff to find a suitable transport. The function is very aggressive + * about choosing UDP or at worst TCP if it can. This is because + * those transports support both the RCPBIND call and the internet + * time service. + * + * Once through, *uaddr is set to the universal address of + * the machine and *netid is set to the local netid for the transport + * that uaddr goes with. On the second call, the netconfig stuff + * is skipped and the uaddr/netid pair are used to fetch the netconfig + * structure and to then contact the machine for the time. + * + * td = "server" - "client" + */ +int +__rpc_get_time_offset(td, srv, thost, uaddr, netid) + struct timeval *td; /* Time difference */ + nis_server *srv; /* NIS Server description */ + char *thost; /* if no server, this is the timehost */ + char **uaddr; /* known universal address */ + struct sockaddr_in *netid; /* known network identifier */ +{ + CLIENT *clnt; /* Client handle */ + endpoint *ep, /* useful endpoints */ + *useep = NULL; /* endpoint of xp */ + char *useua = NULL; /* uaddr of selected xp */ + int epl, i; /* counters */ + enum clnt_stat status; /* result of clnt_call */ + u_long thetime, delta; + int needfree = 0; + struct timeval tv; + int time_valid; + int udp_ep = -1, tcp_ep = -1; + int a1, a2, a3, a4; + char ut[64], ipuaddr[64]; + endpoint teps[32]; + nis_server tsrv; + void (*oldsig)() = NULL; /* old alarm handler */ + struct sockaddr_in sin; + int s = RPC_ANYSOCK, len; + int type = 0; + + td->tv_sec = 0; + td->tv_usec = 0; + + /* + * First check to see if we need to find and address for this + * server. + */ + if (*uaddr == NULL) { + if ((srv != NULL) && (thost != NULL)) { + msg("both timehost and srv pointer used!"); + return (0); + } + if (! srv) { + srv = get_server(netid, thost, &tsrv, teps, 32); + if (srv == NULL) { + msg("unable to contruct server data."); + return (0); + } + needfree = 1; /* need to free data in endpoints */ + } + + ep = srv->ep.ep_val; + epl = srv->ep.ep_len; + + /* Identify the TCP and UDP endpoints */ + for (i = 0; + (i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) { + if (strcasecmp(ep[i].proto, "udp") == 0) + udp_ep = i; + if (strcasecmp(ep[i].proto, "tcp") == 0) + tcp_ep = i; + } + + /* Check to see if it is UDP or TCP */ + if (tcp_ep > -1) { + useep = &ep[tcp_ep]; + useua = ep[tcp_ep].uaddr; + type = SOCK_STREAM; + } else if (udp_ep > -1) { + useep = &ep[udp_ep]; + useua = ep[udp_ep].uaddr; + type = SOCK_DGRAM; + } + + if (useep == NULL) { + msg("no acceptable transport endpoints."); + if (needfree) + free_eps(teps, tsrv.ep.ep_len); + return (0); + } + } + + /* + * Create a sockaddr from the uaddr. + */ + if (*uaddr != NULL) + useua = *uaddr; + + /* Fixup test for NIS+ */ + sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4); + sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4); + useua = &ipuaddr[0]; + + bzero((char *)&sin, sizeof(sin)); + if (uaddr_to_sockaddr(useua, &sin)) { + msg("unable to translate uaddr to sockaddr."); + if (needfree) + free_eps(teps, tsrv.ep.ep_len); + return (0); + } + + /* + * Create the client handle to rpcbind. Note we always try + * version 3 since that is the earliest version that supports + * the RPCB_GETTIME call. Also it is the version that comes + * standard with SVR4. Since most everyone supports TCP/IP + * we could consider trying the rtime call first. + */ + clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0); + if (clnt == NULL) { + msg("unable to create client handle to rpcbind."); + if (needfree) + free_eps(teps, tsrv.ep.ep_len); + return (0); + } + + tv.tv_sec = 5; + tv.tv_usec = 0; + time_valid = 0; + status = clnt_call(clnt, RPCBPROC_GETTIME, xdr_void, NULL, + xdr_u_long, (char *)&thetime, tv); + /* + * The only error we check for is anything but success. In + * fact we could have seen PROGMISMATCH if talking to a 4.1 + * machine (pmap v2) or TIMEDOUT if the net was busy. + */ + if (status == RPC_SUCCESS) + time_valid = 1; + else { + int save; + + /* Blow away possible stale CLNT handle. */ + if (clnt != NULL) { + clnt_destroy(clnt); + clnt = NULL; + } + + /* + * Convert PMAP address into timeservice address + * We take advantage of the fact that we "know" what + * the universal address looks like for inet transports. + * + * We also know that the internet timeservice is always + * listening on port 37. + */ + sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4); + sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4); + + if (uaddr_to_sockaddr(ut, &sin)) { + msg("cannot convert timeservice uaddr to sockaddr."); + goto error; + } + + s = socket(AF_INET, type, 0); + if (s == -1) { + msg("unable to open fd to network."); + goto error; + } + + /* + * Now depending on whether or not we're talking to + * UDP we set a timeout or not. + */ + if (type == SOCK_DGRAM) { + struct timeval timeout = { 20, 0 }; + struct sockaddr_in from; + fd_set readfds; + int res; + + if (sendto(s, &thetime, sizeof(thetime), 0, + (struct sockaddr *)&sin, sizeof(sin)) == -1) { + msg("udp : sendto failed."); + goto error; + } + do { + FD_ZERO(&readfds); + FD_SET(s, &readfds); + res = select(_rpc_dtablesize(), &readfds, + (fd_set *)NULL, (fd_set *)NULL, &timeout); + } while (res < 0 && errno == EINTR); + if (res <= 0) + goto error; + len = sizeof(from); + res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)&from, &len); + if (res == -1) { + msg("recvfrom failed on udp transport."); + goto error; + } + time_valid = 1; + } else { + int res; + + oldsig = (void (*)())signal(SIGALRM, alarm_hndler); + saw_alarm = 0; /* global tracking the alarm */ + alarm(20); /* only wait 20 seconds */ + res = connect(s, (struct sockaddr *)&sin, sizeof(sin)); + if (res == -1) { + msg("failed to connect to tcp endpoint."); + goto error; + } + if (saw_alarm) { + msg("alarm caught it, must be unreachable."); + goto error; + } + res = _read(s, (char *)&thetime, sizeof(thetime)); + if (res != sizeof(thetime)) { + if (saw_alarm) + msg("timed out TCP call."); + else + msg("wrong size of results returned"); + + goto error; + } + time_valid = 1; + } + save = errno; + (void)_close(s); + errno = save; + s = RPC_ANYSOCK; + + if (time_valid) { + thetime = ntohl(thetime); + thetime = thetime - TOFFSET; /* adjust to UNIX time */ + } else + thetime = 0; + } + + gettimeofday(&tv, 0); + +error: + /* + * clean up our allocated data structures. + */ + + if (s != RPC_ANYSOCK) + (void)_close(s); + + if (clnt != NULL) + clnt_destroy(clnt); + + alarm(0); /* reset that alarm if its outstanding */ + if (oldsig) { + signal(SIGALRM, oldsig); + } + + /* + * note, don't free uaddr strings until after we've made a + * copy of them. + */ + if (time_valid) { + if (*uaddr == NULL) + *uaddr = strdup(useua); + + /* Round to the nearest second */ + tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0; + delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec : + tv.tv_sec - thetime; + td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta; + td->tv_usec = 0; + } else { + msg("unable to get the server's time."); + } + + if (needfree) + free_eps(teps, tsrv.ep.ep_len); + + return (time_valid); +} diff --git a/c/src/exec/librpc/src/rpc/auth_unix.c b/c/src/exec/librpc/src/rpc/auth_unix.c index e69de29bb2..885c92a206 100644 --- a/c/src/exec/librpc/src/rpc/auth_unix.c +++ b/c/src/exec/librpc/src/rpc/auth_unix.c @@ -0,0 +1,349 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/auth_unix.c,v 1.12 1999/12/29 05:04:16 peter Exp $"; +#endif + +/* + * auth_unix.c, Implements UNIX style authentication parameters. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The system is very weak. The client uses no encryption for it's + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + * + */ + +#include +#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 +}; + +/* + * This struct is pointed to by the ah_private field of an auth_handle. + */ +struct audata { + struct opaque_auth au_origcred; /* original credentials */ + struct opaque_auth au_shcred; /* short hand cred */ + u_long au_shfaults; /* short hand cache faults */ + char au_marshed[MAX_AUTH_BYTES]; + u_int au_mpos; /* xdr pos at end of marshed */ +}; +#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) + +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. + */ +AUTH * +authunix_create(machname, uid, gid, len, aup_gids) + char *machname; + int uid; + int gid; + register int len; + int *aup_gids; +{ + struct authunix_parms aup; + char mymem[MAX_AUTH_BYTES]; + struct timeval now; + XDR xdrs; + register AUTH *auth; + register struct audata *au; + + /* + * Allocate and set up auth handle + */ + auth = (AUTH *)mem_alloc(sizeof(*auth)); +#ifndef _KERNEL + if (auth == NULL) { + (void)fprintf(stderr, "authunix_create: out of memory\n"); + return (NULL); + } +#endif + au = (struct audata *)mem_alloc(sizeof(*au)); +#ifndef _KERNEL + if (au == NULL) { + (void)fprintf(stderr, "authunix_create: out of memory\n"); + return (NULL); + } +#endif + auth->ah_ops = &auth_unix_ops; + auth->ah_private = (caddr_t)au; + auth->ah_verf = au->au_shcred = _null_auth; + au->au_shfaults = 0; + + /* + * fill in param struct from the given params + */ + (void)gettimeofday(&now, (struct timezone *)0); + 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_gids = aup_gids; + + /* + * Serialize the parameters into origcred + */ + xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); + if (! xdr_authunix_parms(&xdrs, &aup)) + abort(); + au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); + au->au_origcred.oa_flavor = AUTH_UNIX; +#ifdef _KERNEL + au->au_origcred.oa_base = mem_alloc((u_int) len); +#else + if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { + (void)fprintf(stderr, "authunix_create: out of memory\n"); + return (NULL); + } +#endif + memcpy(au->au_origcred.oa_base, mymem, (u_int)len); + + /* + * set auth handle to reflect new cred. + */ + auth->ah_cred = au->au_origcred; + marshal_new_auth(auth); + return (auth); +} + +/* + * Returns an auth handle with parameters determined by doing lots of + * syscalls. + */ +AUTH * +authunix_create_default() +{ + register int len; + char machname[MAX_MACHINE_NAME + 1]; + register int uid; + register int gid; + int gids[NGRPS]; + int i; + gid_t real_gids[NGROUPS]; + + if (gethostname(machname, MAX_MACHINE_NAME) == -1) + abort(); + machname[MAX_MACHINE_NAME] = 0; + uid = (int)geteuid(); + gid = (int)getegid(); + if ((len = getgroups(NGROUPS, real_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)); +} + +/* + * authunix operations + */ + +static void +authunix_nextverf(auth) + AUTH *auth; +{ + /* no action necessary */ +} + +static bool_t +authunix_marshal(auth, xdrs) + AUTH *auth; + XDR *xdrs; +{ + register struct audata *au = AUTH_PRIVATE(auth); + + return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); +} + +static bool_t +authunix_validate(auth, verf) + register AUTH *auth; + struct opaque_auth verf; +{ + register struct audata *au; + XDR xdrs; + + if (verf.oa_flavor == AUTH_SHORT) { + au = AUTH_PRIVATE(auth); + xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE); + + if (au->au_shcred.oa_base != NULL) { + mem_free(au->au_shcred.oa_base, + au->au_shcred.oa_length); + au->au_shcred.oa_base = NULL; + } + if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { + auth->ah_cred = au->au_shcred; + } else { + xdrs.x_op = XDR_FREE; + (void)xdr_opaque_auth(&xdrs, &au->au_shcred); + au->au_shcred.oa_base = NULL; + auth->ah_cred = au->au_origcred; + } + marshal_new_auth(auth); + } + return (TRUE); +} + +static bool_t +authunix_refresh(auth) + register AUTH *auth; +{ + register struct audata *au = AUTH_PRIVATE(auth); + struct authunix_parms aup; + struct timeval now; + XDR xdrs; + register int stat; + + if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { + /* there is no hope. Punt */ + return (FALSE); + } + au->au_shfaults ++; + + /* first deserialize the creds back into a struct authunix_parms */ + aup.aup_machname = NULL; + aup.aup_gids = (int *)NULL; + xdrmem_create(&xdrs, au->au_origcred.oa_base, + au->au_origcred.oa_length, XDR_DECODE); + stat = xdr_authunix_parms(&xdrs, &aup); + if (! stat) + goto done; + + /* update the time and serialize in place */ + (void)gettimeofday(&now, (struct timezone *)0); + aup.aup_time = now.tv_sec; + xdrs.x_op = XDR_ENCODE; + XDR_SETPOS(&xdrs, 0); + stat = xdr_authunix_parms(&xdrs, &aup); + if (! stat) + goto done; + auth->ah_cred = au->au_origcred; + marshal_new_auth(auth); +done: + /* free the struct authunix_parms created by deserializing */ + xdrs.x_op = XDR_FREE; + (void)xdr_authunix_parms(&xdrs, &aup); + XDR_DESTROY(&xdrs); + return (stat); +} + +static void +authunix_destroy(auth) + register AUTH *auth; +{ + register struct audata *au = AUTH_PRIVATE(auth); + + mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); + + if (au->au_shcred.oa_base != NULL) + mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); + + mem_free(auth->ah_private, sizeof(struct audata)); + + if (auth->ah_verf.oa_base != NULL) + mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); + + mem_free((caddr_t)auth, sizeof(*auth)); +} + +/* + * Marshals (pre-serializes) an auth struct. + * sets private data, au_marshed and au_mpos + */ +static void +marshal_new_auth(auth) + register AUTH *auth; +{ + XDR xdr_stream; + register XDR *xdrs = &xdr_stream; + register struct audata *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 { + au->au_mpos = XDR_GETPOS(xdrs); + } + XDR_DESTROY(xdrs); +} diff --git a/c/src/exec/librpc/src/rpc/authdes_prot.c b/c/src/exec/librpc/src/rpc/authdes_prot.c index e69de29bb2..14679c00a9 100644 --- a/c/src/exec/librpc/src/rpc/authdes_prot.c +++ b/c/src/exec/librpc/src/rpc/authdes_prot.c @@ -0,0 +1,82 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI"; +#endif +/* + * 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. + */ + +/* + * authdes_prot.c, XDR routines for DES authentication + */ + +#include +#include +#include +#include + +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +bool_t +xdr_authdes_cred(xdrs, cred) + XDR *xdrs; + struct authdes_cred *cred; +{ + /* + * Unrolled xdr + */ + ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind)); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, MAXNETNAMELEN)); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, sizeof(cred->adc_fullname.window))); + return (TRUE); + case ADN_NICKNAME: + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, sizeof(cred->adc_nickname))); + return (TRUE); + default: + return (FALSE); + } +} + + +bool_t +xdr_authdes_verf(xdrs, verf) + register XDR *xdrs; + register struct authdes_verf *verf; +{ + /* + * Unrolled xdr + */ + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u))); + return (TRUE); +} diff --git a/c/src/exec/librpc/src/rpc/authunix_prot.c b/c/src/exec/librpc/src/rpc/authunix_prot.c index e69de29bb2..022fac0686 100644 --- a/c/src/exec/librpc/src/rpc/authunix_prot.c +++ b/c/src/exec/librpc/src/rpc/authunix_prot.c @@ -0,0 +1,68 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/authunix_prot.c,v 1.6 1999/08/28 00:00:33 peter Exp $"; +#endif + +/* + * authunix_prot.c + * XDR for UNIX style authentication parameters for RPC + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + + +#include +#include +#include +#include + +/* + * XDR for unix authentication parameters. + */ +bool_t +xdr_authunix_parms(xdrs, p) + register XDR *xdrs; + register struct authunix_parms *p; +{ + + 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) ) { + return (TRUE); + } + return (FALSE); +} + diff --git a/c/src/exec/librpc/src/rpc/bindresvport.3 b/c/src/exec/librpc/src/rpc/bindresvport.3 index e69de29bb2..02a079decc 100644 --- a/c/src/exec/librpc/src/rpc/bindresvport.3 +++ b/c/src/exec/librpc/src/rpc/bindresvport.3 @@ -0,0 +1,106 @@ +.\" @(#)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 2000/01/27 02:55:01 bde Exp $ +.\" +.Dd January 27, 2000 +.Dt BINDRESVPORT 3 +.Os +.Sh NAME +.Nm bindresvport , +.Nm bindresvport_sa +.Ndbind a socket to a privileged IP port +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn bindresvport "int sd" "struct sockaddr_in *sin" +.Ft int +.Fn bindresvport_sa "int sd" "struct sockaddr *sa" +.Sh DESCRIPTION +.Fn bindresvport +and +.Fn bindresvport_sa +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 +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. +.Pp +It is legal to pass null pointer to +.Va sin . +In this case, the caller cannot get the port number +.Fn bindresvport +has picked. +.Pp +Function prototype of +.Fn bindresvport +is biased to +.Dv AF_INET +socket. +.Fn bindresvport_sa +acts exactly the same, with more neutral function prototype. +Note that both functions behave exactly the same, and +both support +.Dv AF_INET6 +sockets as well as +.Dv AF_INET +sockets. +.Sh RETURN VALUES +.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. +.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. +.El +.Sh "SEE ALSO" +.Xr bind 2 , +.Xr socket 2 , +.Xr rresvport 3 , +.Xr rresvport_af 3 diff --git a/c/src/exec/librpc/src/rpc/bindresvport.c b/c/src/exec/librpc/src/rpc/bindresvport.c index e69de29bb2..bb97570b88 100644 --- a/c/src/exec/librpc/src/rpc/bindresvport.c +++ b/c/src/exec/librpc/src/rpc/bindresvport.c @@ -0,0 +1,147 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/ +/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/ +/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.12 2000/01/26 09:02:42 shin Exp $"; +#endif + +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + * + * Portions Copyright(C) 1996, Jason Downs. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Bind a socket to a privileged port for whatever protocol. + */ +int +bindresvport_sa(sd, sa) + int sd; + struct sockaddr *sa; +{ + int old, error, af; + struct sockaddr myaddr; + struct sockaddr_in *sin; +#if (defined(AF_INET6) && defined(IPPROTO_IPV6)) + struct sockaddr_in6 *sin6; +#endif + int proto, portrange, portlow; + u_int16_t port; + int salen; + + if (sa == NULL) { + salen = sizeof(myaddr); + sa = (struct sockaddr *)&myaddr; + + if (getsockname(sd, sa, &salen) == -1) + return -1; /* errno is correctly set */ + + af = sa->sa_family; + memset(&myaddr, 0, salen); + } else + af = sa->sa_family; + + if (af == 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; +#if (defined(AF_INET6) && defined(IPPROTO_IPV6)) + } else if (af == 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; +#endif + } else { + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + sa->sa_len = salen; + + if (port == 0) { + int oldlen = sizeof(old); + + error = getsockopt(sd, proto, portrange, &old, &oldlen); + if (error < 0) + return (error); + + error = setsockopt(sd, proto, portrange, &portlow, + sizeof(portlow)); + if (error < 0) + return (error); + } + + error = bind(sd, sa, salen); + + if (port == 0) { + int saved_errno = errno; + + if (error) { + if (setsockopt(sd, proto, portrange, &old, + sizeof(old)) < 0) + errno = saved_errno; + return (error); + } + + if (sa != (struct sockaddr *)&myaddr) { + /* Hmm, what did the kernel assign... */ + if (getsockname(sd, sa, &salen) < 0) + errno = saved_errno; + return (error); + } + } + return (error); +} + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport(sd, sin) + int sd; + struct sockaddr_in *sin; +{ + return bindresvport_sa(sd, (struct sockaddr *)sin); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_generic.c b/c/src/exec/librpc/src/rpc/clnt_generic.c index e69de29bb2..d387fae4c0 100644 --- a/c/src/exec/librpc/src/rpc/clnt_generic.c +++ b/c/src/exec/librpc/src/rpc/clnt_generic.c @@ -0,0 +1,141 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/ +/*static char *sccsid = "from: @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_generic.c,v 1.9 1999/08/28 00:00:35 peter Exp $"; +#endif + +/* + * Copyright (C) 1987, Sun Microsystems, Inc. + */ +#include +#include +#include +#include +#include + +/* + * Generic client creation: takes (hostname, program-number, protocol) and + * returns client handle. Default options are set, which the user can + * change using the rpc equivalent of ioctl()'s. + */ +CLIENT * +clnt_create(hostname, prog, vers, proto) + char *hostname; + u_long prog; + u_long vers; + char *proto; +{ + struct hostent *h; + struct protoent *p; + struct sockaddr_in sin; +#ifndef __rtems__ + struct sockaddr_un sun; +#endif + int sock; + struct timeval tv; + CLIENT *client; + +#ifndef __rtems__ + 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); + } +#endif + + h = gethostbyname(hostname); + if (h == NULL) { + rpc_createerr.cf_stat = RPC_UNKNOWNHOST; + return (NULL); + } + if (h->h_addrtype != AF_INET) { + /* + * Only support INET for now + */ + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; + return (NULL); + } + 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_UNKNOWNPROTO; + rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; + return (NULL); + } + sock = RPC_ANYSOCK; + switch (p->p_proto) { + case IPPROTO_UDP: + tv.tv_sec = 5; + tv.tv_usec = 0; + client = clntudp_create(&sin, prog, vers, tv, &sock); + if (client == NULL) { + return (NULL); + } +#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) { + 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; + default: + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; + return (NULL); + } + return (client); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_perror.c b/c/src/exec/librpc/src/rpc/clnt_perror.c index e69de29bb2..720583ba54 100644 --- a/c/src/exec/librpc/src/rpc/clnt_perror.c +++ b/c/src/exec/librpc/src/rpc/clnt_perror.c @@ -0,0 +1,254 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_perror.c,v 1.11 1999/08/28 00:00:35 peter Exp $"; +#endif + +/* + * clnt_perror.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ +#include +#include +#include +#include +#include +#include +#include + +static char *auth_errmsg(); +#define CLNT_PERROR_BUFLEN 256 + +#define buf ((char *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->clnt_perror_buf) + +static char * +_buf() +{ + + if (buf == 0) + buf = (char *)malloc(CLNT_PERROR_BUFLEN); + return (buf); +} + +/* + * Print reply error info + */ +char * +clnt_sperror(rpch, s) + CLIENT *rpch; + char *s; +{ + struct rpc_err e; + char *err; + char *str = _buf(); + char *strstart = str; + + if (str == 0) + return (0); + CLNT_GETERR(rpch, &e); + + (void) sprintf(str, "%s: %s", s, clnt_sperrno(e.re_status)); + str += strlen(str); + + switch (e.re_status) { + case RPC_SUCCESS: + case RPC_CANTENCODEARGS: + case RPC_CANTDECODERES: + case RPC_TIMEDOUT: + case RPC_PROGUNAVAIL: + case RPC_PROCUNAVAIL: + case RPC_CANTDECODEARGS: + case RPC_SYSTEMERROR: + case RPC_UNKNOWNHOST: + case RPC_UNKNOWNPROTO: + case RPC_PMAPFAILURE: + case RPC_PROGNOTREGISTERED: + case RPC_FAILED: + break; + + case RPC_CANTSEND: + case RPC_CANTRECV: + (void) snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart), + "; errno = %s\n", strerror(e.re_errno)); + break; + + case RPC_VERSMISMATCH: + (void) sprintf(str, + "; low version = %lu, high version = %lu\n", + (u_long)e.re_vers.low, (u_long)e.re_vers.high); + break; + + case RPC_AUTHERROR: + err = auth_errmsg(e.re_why); + (void) sprintf(str,"; why = "); + str += strlen(str); + if (err != NULL) { + (void) sprintf(str, "%s\n",err); + } else { + (void) sprintf(str, + "(unknown authentication error - %d)\n", + (int) e.re_why); + } + break; + + case RPC_PROGVERSMISMATCH: + (void) sprintf(str, + "; low version = %lu, high version = %lu\n", + (u_long)e.re_vers.low, (u_long)e.re_vers.high); + break; + + default: /* unknown */ + (void) sprintf(str, + "; s1 = %lu, s2 = %lu\n", + (long)e.re_lb.s1, (long)e.re_lb.s2); + break; + } + strstart[CLNT_PERROR_BUFLEN-2] = '\n'; + strstart[CLNT_PERROR_BUFLEN-1] = '\0'; + return(strstart) ; +} + +void +clnt_perror(rpch, s) + CLIENT *rpch; + char *s; +{ + (void) fprintf(stderr,"%s\n",clnt_sperror(rpch,s)); +} + + +static const char *const rpc_errlist[] = { + "RPC: Success", /* 0 - RPC_SUCCESS */ + "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */ + "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */ + "RPC: Unable to send", /* 3 - RPC_CANTSEND */ + "RPC: Unable to receive", /* 4 - RPC_CANTRECV */ + "RPC: Timed out", /* 5 - RPC_TIMEDOUT */ + "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */ + "RPC: Authentication error", /* 7 - RPC_AUTHERROR */ + "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */ + "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */ + "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */ + "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */ + "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */ + "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */ + "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */ + "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */ + "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */ + "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */ +}; + + +/* + * This interface for use by clntrpc + */ +char * +clnt_sperrno(stat) + enum clnt_stat stat; +{ + unsigned int errnum = stat; + + if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) + return (char *)rpc_errlist[errnum]; + + return ("RPC: (unknown error code)"); +} + +void +clnt_perrno(num) + enum clnt_stat num; +{ + (void) fprintf(stderr,"%s\n",clnt_sperrno(num)); +} + + +char * +clnt_spcreateerror(s) + char *s; +{ + char *str = _buf(); + + if (str == 0) + return(0); + switch (rpc_createerr.cf_stat) { + case RPC_PMAPFAILURE: + (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, + clnt_sperrno(rpc_createerr.cf_stat), + clnt_sperrno(rpc_createerr.cf_error.re_status)); + break; + + case RPC_SYSTEMERROR: + (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, + clnt_sperrno(rpc_createerr.cf_stat), + strerror(rpc_createerr.cf_error.re_errno)); + break; + default: + (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s\n", s, + clnt_sperrno(rpc_createerr.cf_stat)); + break; + } + str[CLNT_PERROR_BUFLEN-2] = '\n'; + str[CLNT_PERROR_BUFLEN-1] = '\0'; + return (str); +} + +void +clnt_pcreateerror(s) + char *s; +{ + (void) fprintf(stderr,"%s\n",clnt_spcreateerror(s)); +} + +static const char *const auth_errlist[] = { + "Authentication OK", /* 0 - AUTH_OK */ + "Invalid client credential", /* 1 - AUTH_BADCRED */ + "Server rejected credential", /* 2 - AUTH_REJECTEDCRED */ + "Invalid client verifier", /* 3 - AUTH_BADVERF */ + "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */ + "Client credential too weak", /* 5 - AUTH_TOOWEAK */ + "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */ + "Failed (unspecified error)" /* 7 - AUTH_FAILED */ +}; + +static char * +auth_errmsg(stat) + enum auth_stat stat; +{ + unsigned int errnum = stat; + + if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0]))) + return (char *)auth_errlist[errnum]; + + return(NULL); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_raw.c b/c/src/exec/librpc/src/rpc/clnt_raw.c index e69de29bb2..a343c49068 100644 --- a/c/src/exec/librpc/src/rpc/clnt_raw.c +++ b/c/src/exec/librpc/src/rpc/clnt_raw.c @@ -0,0 +1,243 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_raw.c,v 1.10 1999/08/28 00:00:36 peter Exp $"; +#endif + +/* + * clnt_raw.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Memory based rpc for simple testing and timing. + * Interface to create an rpc client and server in the same process. + * This lets us similate rpc and get round trip overhead, without + * any interference from the kernal. + */ + +#include +#include +#include + +#define MCALL_MSG_SIZE 24 + +/* + * This is the "network" we will be moving stuff over. + */ +struct clnt_raw_private { + CLIENT client_object; + XDR xdr_stream; + char _raw_buf[UDPMSGSIZE]; + char mashl_callmsg[MCALL_MSG_SIZE]; + u_int mcnt; +}; +#define clntraw_private ((struct clnt_raw_private *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->clnt_raw_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(); + +/* + * Create a client handle for memory based rpc. + */ +CLIENT * +clntraw_create(prog, vers) + u_long prog; + u_long vers; +{ + register struct clnt_raw_private *clp = clntraw_private; + struct rpc_msg call_msg; + XDR *xdrs = &clp->xdr_stream; + CLIENT *client = &clp->client_object; + + if (clp == 0) { + clp = (struct clnt_raw_private *)calloc(1, sizeof (*clp)); + if (clp == 0) + return (0); + clntraw_private = clp; + } + /* + * pre-serialize the static part of the call msg and stash it away + */ + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + 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."); + } + clp->mcnt = XDR_GETPOS(xdrs); + XDR_DESTROY(xdrs); + + /* + * Set xdrmem for client/server shared buffer + */ + xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE); + + /* + * create client handle + */ + client->cl_ops = &client_ops; + client->cl_auth = authnone_create(); + return (client); +} + +static enum clnt_stat +clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout) + CLIENT *h; + u_long proc; + xdrproc_t xargs; + caddr_t argsp; + xdrproc_t xresults; + caddr_t resultsp; + struct timeval timeout; +{ + register struct clnt_raw_private *clp = clntraw_private; + register XDR *xdrs = &clp->xdr_stream; + struct rpc_msg msg; + enum clnt_stat status; + struct rpc_err error; + + if (clp == 0) + return (RPC_FAILED); +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)) || + (! AUTH_MARSHALL(h->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) { + return (RPC_CANTENCODEARGS); + } + (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ + + /* + * We have to call server input routine here because this is + * all going on in one process. Yuk. + */ + svc_getreq(1); + + /* + * get results + */ + xdrs->x_op = XDR_DECODE; + XDR_SETPOS(xdrs, 0); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = resultsp; + msg.acpted_rply.ar_results.proc = xresults; + if (! xdr_replymsg(xdrs, &msg)) + return (RPC_CANTDECODERES); + _seterr_reply(&msg, &error); + status = error.re_status; + + if (status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { + status = RPC_AUTHERROR; + } + } /* end successful completion */ + else { + if (AUTH_REFRESH(h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + + if (status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { + status = RPC_AUTHERROR; + } + if (msg.acpted_rply.ar_verf.oa_base != NULL) { + xdrs->x_op = XDR_FREE; + (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf)); + } + } + + return (status); +} + +static void +clntraw_geterr() +{ +} + + +static bool_t +clntraw_freeres(cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + register struct clnt_raw_private *clp = clntraw_private; + register XDR *xdrs = &clp->xdr_stream; + bool_t rval; + + if (clp == 0) + { + rval = (bool_t) RPC_FAILED; + return (rval); + } + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clntraw_abort() +{ +} + +static bool_t +clntraw_control() +{ + return (FALSE); +} + +static void +clntraw_destroy() +{ +} diff --git a/c/src/exec/librpc/src/rpc/clnt_simple.c b/c/src/exec/librpc/src/rpc/clnt_simple.c index e69de29bb2..e8f92bc657 100644 --- a/c/src/exec/librpc/src/rpc/clnt_simple.c +++ b/c/src/exec/librpc/src/rpc/clnt_simple.c @@ -0,0 +1,123 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_simple.c,v 1.12 2000/01/27 23:06:35 jasone Exp $"; +#endif + +/* + * clnt_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct call_rpc_private { + CLIENT *client; + int socket; + int oldprognum, oldversnum, valid; + char *oldhost; +}; +#define callrpc_private ((struct call_rpc_private *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->call_rpc_private) + +int +callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) + char *host; + int prognum, versnum, procnum; + xdrproc_t inproc, outproc; + char *in, *out; +{ + register struct call_rpc_private *crp = callrpc_private; + struct sockaddr_in server_addr; + enum clnt_stat clnt_stat; + struct hostent *hp; + struct timeval timeout, tottimeout; + + if (crp == 0) { + crp = (struct call_rpc_private *)calloc(1, sizeof (*crp)); + if (crp == 0) + return (0); + callrpc_private = crp; + } + if (crp->oldhost == NULL) { + crp->oldhost = malloc(MAXHOSTNAMELEN); + crp->oldhost[0] = 0; + crp->socket = RPC_ANYSOCK; + } + if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum + && strcmp(crp->oldhost, host) == 0) { + /* reuse old client */ + } else { + crp->valid = 0; + if (crp->socket != -1) + (void)_close(crp->socket); + crp->socket = RPC_ANYSOCK; + if (crp->client) { + clnt_destroy(crp->client); + crp->client = NULL; + } + if ((hp = gethostbyname(host)) == NULL) + return ((int) RPC_UNKNOWNHOST); + timeout.tv_usec = 0; + timeout.tv_sec = 5; + memset(&server_addr, 0, sizeof(server_addr)); + memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length); + server_addr.sin_len = sizeof(struct sockaddr_in); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + if ((crp->client = clntudp_create(&server_addr, (u_long)prognum, + (u_long)versnum, timeout, &crp->socket)) == NULL) + return ((int) rpc_createerr.cf_stat); + crp->valid = 1; + crp->oldprognum = prognum; + crp->oldversnum = versnum; + (void) strcpy(crp->oldhost, host); + } + tottimeout.tv_sec = 25; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call(crp->client, procnum, inproc, in, + outproc, out, tottimeout); + /* + * if call failed, empty cache + */ + if (clnt_stat != RPC_SUCCESS) + crp->valid = 0; + return ((int) clnt_stat); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_tcp.c b/c/src/exec/librpc/src/rpc/clnt_tcp.c index e69de29bb2..2b094126b3 100644 --- a/c/src/exec/librpc/src/rpc/clnt_tcp.c +++ b/c/src/exec/librpc/src/rpc/clnt_tcp.c @@ -0,0 +1,580 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_tcp.c,v 1.14 2000/01/27 23:06:36 jasone Exp $"; +#endif + +/* + * clnt_tcp.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * TCP based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCALL_MSG_SIZE 24 + +static int readtcp(); +static int writetcp(); + +static enum clnt_stat clnttcp_call(); +static void clnttcp_abort(); +static void clnttcp_geterr(); +static bool_t clnttcp_freeres(); +static bool_t clnttcp_control(); +static void clnttcp_destroy(); + +static struct clnt_ops tcp_ops = { + clnttcp_call, + clnttcp_abort, + clnttcp_geterr, + clnttcp_freeres, + clnttcp_destroy, + clnttcp_control +}; + +struct ct_data { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_in ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +CLIENT * +clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + struct sockaddr_in *raddr; + u_long prog; + u_long vers; + register int *sockp; + u_int sendsz; + u_int recvsz; +{ + CLIENT *h; + register struct ct_data *ct = NULL; + struct timeval now; + struct rpc_msg call_msg; + static u_int32_t disrupt; + + if (disrupt == 0) + disrupt = (u_int32_t)(long)raddr; + + h = (CLIENT *)mem_alloc(sizeof(*h)); + if (h == NULL) { + (void)fprintf(stderr, "clnttcp_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + ct = (struct ct_data *)mem_alloc(sizeof(*ct)); + if (ct == NULL) { + (void)fprintf(stderr, "clnttcp_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + + /* + * If no port number given ask the pmap for one + */ + if (raddr->sin_port == 0) { + u_short port; + if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) { + mem_free((caddr_t)ct, sizeof(struct ct_data)); + mem_free((caddr_t)h, sizeof(CLIENT)); + return ((CLIENT *)NULL); + } + raddr->sin_port = htons(port); + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) { + *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + (void)bindresvport(*sockp, (struct sockaddr_in *)0); + if ((*sockp < 0) + || (connect(*sockp, (struct sockaddr *)raddr, + sizeof(*raddr)) < 0)) { + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + if (*sockp != -1) + (void)_close(*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } else { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + (void)gettimeofday(&now, (struct timezone *)0); + call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec; + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, + XDR_ENCODE); + if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { + if (ct->ct_closeit) { + (void)_close(*sockp); + } + goto fooy; + } + ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); + XDR_DESTROY(&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t)ct, readtcp, writetcp); + h->cl_ops = &tcp_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create(); + return (h); + +fooy: + /* + * Something goofed, free stuff and barf + */ + if (ct) + mem_free((caddr_t)ct, sizeof(struct ct_data)); + if (h) + mem_free((caddr_t)h, sizeof(CLIENT)); + return ((CLIENT *)NULL); +} + +static enum clnt_stat +clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) + register CLIENT *h; + u_long proc; + xdrproc_t xdr_args; + caddr_t args_ptr; + xdrproc_t xdr_results; + caddr_t results_ptr; + struct timeval timeout; +{ + register struct ct_data *ct = (struct ct_data *) h->cl_private; + register XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */ + register bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 + && timeout.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl(--(*msg_x_id)); + if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || + (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(h->cl_auth, xdrs)) || + (! (*xdr_args)(xdrs, args_ptr))) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void)xdrrec_endofrecord(xdrs, TRUE); + return (ct->ct_error.re_status); + } + if (! xdrrec_endofrecord(xdrs, shipnow)) + return (ct->ct_error.re_status = RPC_CANTSEND); + if (! shipnow) + return (RPC_SUCCESS); + /* + * Hack to provide rpc-based message passing + */ + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { + return(ct->ct_error.re_status = RPC_TIMEDOUT); + } + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = xdr_void; + if (! xdrrec_skiprecord(xdrs)) + return (ct->ct_error.re_status); + /* now decode and validate the response header */ + if (! xdr_replymsg(xdrs, &reply_msg)) { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return (ct->ct_error.re_status); + } + if (reply_msg.rm_xid == x_id) + break; + } + + /* + * process header + */ + _seterr_reply(&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } else if (! (*xdr_results)(xdrs, results_ptr)) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { + xdrs->x_op = XDR_FREE; + (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH(h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return (ct->ct_error.re_status); +} + +static void +clnttcp_geterr(h, errp) + CLIENT *h; + struct rpc_err *errp; +{ + register struct ct_data *ct = + (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clnttcp_freeres(cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + register struct ct_data *ct = (struct ct_data *)cl->cl_private; + register XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clnttcp_abort() +{ +} + + +static bool_t +clnttcp_control(cl, request, info) + CLIENT *cl; + int request; + char *info; +{ + register struct ct_data *ct = (struct ct_data *)cl->cl_private; + register struct timeval *tv; + int len; + + switch (request) { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + if (info == NULL) + return(FALSE); + tv = (struct timeval *)info; + ct->ct_wait.tv_sec = tv->tv_sec; + ct->ct_wait.tv_usec = tv->tv_usec; + ct->ct_waitset = TRUE; + break; + case CLGET_TIMEOUT: + if (info == NULL) + return(FALSE); + *(struct timeval *)info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + if (info == NULL) + return(FALSE); + *(struct sockaddr_in *)info = ct->ct_addr; + break; + case CLGET_FD: + if (info == NULL) + return(FALSE); + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + if (info == NULL) + return(FALSE); + *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1); + /* decrement by 1 as clnttcp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + if (info == NULL) + return(FALSE); + *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + if (info == NULL) + return(FALSE); + *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_LOCAL_ADDR: + len = sizeof(struct sockaddr); + if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0) + return(FALSE); + break; + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return (FALSE); + } + return (TRUE); +} + + +static void +clnttcp_destroy(h) + CLIENT *h; +{ + register struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) { + (void)_close(ct->ct_sock); + } + XDR_DESTROY(&(ct->ct_xdrs)); + mem_free((caddr_t)ct, sizeof(struct ct_data)); + mem_free((caddr_t)h, sizeof(CLIENT)); +} + +/* + * Interface between xdr serializer and tcp connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readtcp(ct, buf, len) + register struct ct_data *ct; + caddr_t buf; + register int len; +{ + fd_set *fds, readfds; + struct timeval start, after, duration, delta, tmp, tv; + int r, save_errno; + + if (len == 0) + return (0); + + if (ct->ct_sock + 1 > FD_SETSIZE) { + int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask); + fds = (fd_set *)malloc(bytes); + if (fds == NULL) + return (-1); + memset(fds, 0, bytes); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + gettimeofday(&start, NULL); + delta = ct->ct_wait; + while (TRUE) { + /* XXX we know the other bits are still clear */ + FD_SET(ct->ct_sock, fds); + tv = delta; /* in case select writes back */ + r = select(ct->ct_sock+1, fds, NULL, NULL, &tv); + save_errno = errno; + + gettimeofday(&after, NULL); + timersub(&start, &after, &duration); + timersub(&ct->ct_wait, &duration, &tmp); + delta = tmp; + if (delta.tv_sec < 0 || !timerisset(&delta)) + r = 0; + + switch (r) { + case 0: + if (fds != &readfds) + free(fds); + ct->ct_error.re_status = RPC_TIMEDOUT; + return (-1); + + case -1: + if (errno == EINTR) + continue; + if (fds != &readfds) + free(fds); + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = save_errno; + return (-1); + } + break; + } + switch (len = _read(ct->ct_sock, buf, len)) { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return (len); +} + +static int +writetcp(ct, buf, len) + struct ct_data *ct; + caddr_t buf; + int len; +{ + register int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = _write(ct->ct_sock, buf, cnt)) == -1) { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return (-1); + } + } + return (len); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_udp.c b/c/src/exec/librpc/src/rpc/clnt_udp.c index e69de29bb2..304d451d64 100644 --- a/c/src/exec/librpc/src/rpc/clnt_udp.c +++ b/c/src/exec/librpc/src/rpc/clnt_udp.c @@ -0,0 +1,567 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_udp.c,v 1.15 2000/01/27 23:06:36 jasone Exp $"; +#endif + +/* + * clnt_udp.c, Implements a UDP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * UDP bases client side rpc operations + */ +static enum clnt_stat clntudp_call(); +static void clntudp_abort(); +static void clntudp_geterr(); +static bool_t clntudp_freeres(); +static bool_t clntudp_control(); +static void clntudp_destroy(); + +static struct clnt_ops udp_ops = { + clntudp_call, + clntudp_abort, + clntudp_geterr, + clntudp_freeres, + clntudp_destroy, + clntudp_control +}; + +/* + * Private data kept per client handle + */ +struct cu_data { + int cu_sock; + bool_t cu_closeit; + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; + struct timeval cu_total; + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; + char *cu_outbuf; + u_int cu_recvsz; + char cu_inbuf[1]; +}; + +/* + * Create a UDP based client handle. + * If *sockp<0, *sockp is set to a newly created UPD socket. + * If raddr->sin_port is 0 a binder on the remote machine + * is consulted for the correct port number. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is initialized to null authentication. + * Caller may wish to set this something more useful. + * + * wait is the amount of time used between retransmitting a call if + * no response has been heard; retransmition occurs until the actual + * rpc call times out. + * + * sendsz and recvsz are the maximum allowable packet sizes that can be + * sent and received. + */ +CLIENT * +clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + struct sockaddr_in *raddr; + u_long program; + u_long version; + struct timeval wait; + register int *sockp; + u_int sendsz; + u_int recvsz; +{ + CLIENT *cl; + register struct cu_data *cu = NULL; + struct timeval now; + struct rpc_msg call_msg; + static u_int32_t disrupt; + + if (disrupt == 0) + disrupt = (u_int32_t)(long)raddr; + + cl = (CLIENT *)mem_alloc(sizeof(CLIENT)); + if (cl == NULL) { + (void) fprintf(stderr, "clntudp_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + sendsz = ((sendsz + 3) / 4) * 4; + recvsz = ((recvsz + 3) / 4) * 4; + cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz); + if (cu == NULL) { + (void) fprintf(stderr, "clntudp_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; + + (void)gettimeofday(&now, (struct timezone *)0); + if (raddr->sin_port == 0) { + u_short port; + if ((port = + pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) { + goto fooy; + } + raddr->sin_port = htons(port); + } + cl->cl_ops = &udp_ops; + cl->cl_private = (caddr_t)cu; + cu->cu_raddr = *raddr; + cu->cu_rlen = sizeof (cu->cu_raddr); + cu->cu_wait = wait; + cu->cu_total.tv_sec = -1; + cu->cu_total.tv_usec = -1; + cu->cu_sendsz = sendsz; + cu->cu_recvsz = recvsz; + call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec; + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = program; + call_msg.rm_call.cb_vers = version; + xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, + sendsz, XDR_ENCODE); + if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) { + goto fooy; + } + cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); + if (*sockp < 0) { + int dontblock = 1; + + *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (*sockp < 0) { + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + /* attempt to bind to priv port */ + (void)bindresvport(*sockp, (struct sockaddr_in *)0); + /* the sockets rpc controls are non-blocking */ + (void)ioctl(*sockp, FIONBIO, (char *) &dontblock); + cu->cu_closeit = TRUE; + } else { + cu->cu_closeit = FALSE; + } + cu->cu_sock = *sockp; + cl->cl_auth = authnone_create(); + return (cl); +fooy: + if (cu) + mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz); + if (cl) + mem_free((caddr_t)cl, sizeof(CLIENT)); + return ((CLIENT *)NULL); +} + +CLIENT * +clntudp_create(raddr, program, version, wait, sockp) + struct sockaddr_in *raddr; + u_long program; + u_long version; + struct timeval wait; + register int *sockp; +{ + + return(clntudp_bufcreate(raddr, program, version, wait, sockp, + UDPMSGSIZE, UDPMSGSIZE)); +} + +static enum clnt_stat +clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) + register CLIENT *cl; /* client handle */ + u_long proc; /* procedure number */ + xdrproc_t xargs; /* xdr routine for args */ + caddr_t argsp; /* pointer to args */ + xdrproc_t xresults; /* xdr routine for results */ + caddr_t resultsp; /* pointer to results */ + struct timeval utimeout; /* seconds to wait before giving up */ +{ + register struct cu_data *cu = (struct cu_data *)cl->cl_private; + register XDR *xdrs; + register int outlen; + register int inlen; + int fromlen; + fd_set *fds, readfds; + struct sockaddr_in from; + struct rpc_msg reply_msg; + XDR reply_xdrs; + struct timeval time_waited, start, after, tmp1, tmp2, tv; + bool_t ok; + int nrefreshes = 2; /* number of times to refresh cred */ + struct timeval timeout; + + if (cu->cu_total.tv_usec == -1) + timeout = utimeout; /* use supplied timeout */ + else + timeout = cu->cu_total; /* use default timeout */ + + if (cu->cu_sock + 1 > FD_SETSIZE) { + int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask); + fds = (fd_set *)malloc(bytes); + if (fds == NULL) + return (cu->cu_error.re_status = RPC_CANTSEND); + memset(fds, 0, bytes); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + timerclear(&time_waited); + +call_again: + xdrs = &(cu->cu_outxdrs); + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, cu->cu_xdrpos); + /* + * the transaction is the first thing in the out buffer + */ + (*(u_short *)(cu->cu_outbuf))++; + if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) { + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + } + outlen = (int)XDR_GETPOS(xdrs); + +send_again: + if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, + (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) { + cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_CANTSEND); + } + + /* + * Hack to provide rpc-based message passing + */ + if (!timerisset(&timeout)) { + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_TIMEDOUT); + } + /* + * sub-optimal code appears here because we have + * some clock time to spare while the packets are in flight. + * (We assume that this is actually only executed once.) + */ + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + + gettimeofday(&start, NULL); + for (;;) { + /* XXX we know the other bits are still clear */ + FD_SET(cu->cu_sock, fds); + tv = cu->cu_wait; + switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) { + + case 0: + timeradd(&time_waited, &cu->cu_wait, &tmp1); + time_waited = tmp1; + if (timercmp(&time_waited, &timeout, <)) + goto send_again; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_TIMEDOUT); + + case -1: + if (errno == EINTR) { + gettimeofday(&after, NULL); + timersub(&after, &start, &tmp1); + timeradd(&time_waited, &tmp1, &tmp2); + time_waited = tmp2; + if (timercmp(&time_waited, &timeout, <)) + continue; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_TIMEDOUT); + } + cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_CANTRECV); + } + + do { + fromlen = sizeof(struct sockaddr); + inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, + (int) cu->cu_recvsz, 0, + (struct sockaddr *)&from, &fromlen); + } while (inlen < 0 && errno == EINTR); + if (inlen < 0) { + if (errno == EWOULDBLOCK) + continue; + cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_CANTRECV); + } + if (inlen < sizeof(u_int32_t)) + continue; + /* see if reply transaction id matches sent id */ + if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf))) + continue; + /* we now assume we have the proper reply */ + break; + } + + /* + * now decode and validate the response + */ + xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE); + ok = xdr_replymsg(&reply_xdrs, &reply_msg); + /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ + if (ok) { + _seterr_reply(&reply_msg, &(cu->cu_error)); + if (cu->cu_error.re_status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(cl->cl_auth, + &reply_msg.acpted_rply.ar_verf)) { + cu->cu_error.re_status = RPC_AUTHERROR; + cu->cu_error.re_why = AUTH_INVALIDRESP; + } + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { + xdrs->x_op = XDR_FREE; + (void)xdr_opaque_auth(xdrs, + &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else { + /* maybe our credentials need to be refreshed ... */ + if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) { + nrefreshes--; + goto call_again; + } + } /* end of unsuccessful completion */ + } /* end of valid reply message */ + else { + /* + * It's possible for xdr_replymsg() to fail partway + * through its attempt to decode the result from the + * server. If this happens, it will leave the reply + * structure partially populated with dynamically + * allocated memory. (This can happen if someone uses + * clntudp_bufcreate() to create a CLIENT handle and + * specifies a receive buffer size that is too small.) + * This memory must be free()ed to avoid a leak. + */ + int op = reply_xdrs.x_op; + reply_xdrs.x_op = XDR_FREE; + xdr_replymsg(&reply_xdrs, &reply_msg); + reply_xdrs.x_op = op; + cu->cu_error.re_status = RPC_CANTDECODERES; + } + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status); +} + +static void +clntudp_geterr(cl, errp) + CLIENT *cl; + struct rpc_err *errp; +{ + register struct cu_data *cu = (struct cu_data *)cl->cl_private; + + *errp = cu->cu_error; +} + + +static bool_t +clntudp_freeres(cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + register struct cu_data *cu = (struct cu_data *)cl->cl_private; + register XDR *xdrs = &(cu->cu_outxdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clntudp_abort(/*h*/) + /*CLIENT *h;*/ +{ +} + + +static bool_t +clntudp_control(cl, request, info) + CLIENT *cl; + int request; + char *info; +{ + register struct cu_data *cu = (struct cu_data *)cl->cl_private; + register struct timeval *tv; + int len; + + switch (request) { + case CLSET_FD_CLOSE: + cu->cu_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + cu->cu_closeit = FALSE; + break; + case CLSET_TIMEOUT: + if (info == NULL) + return(FALSE); + tv = (struct timeval *)info; + cu->cu_total.tv_sec = tv->tv_sec; + cu->cu_total.tv_usec = tv->tv_usec; + break; + case CLGET_TIMEOUT: + if (info == NULL) + return(FALSE); + *(struct timeval *)info = cu->cu_total; + break; + case CLSET_RETRY_TIMEOUT: + if (info == NULL) + return(FALSE); + tv = (struct timeval *)info; + cu->cu_wait.tv_sec = tv->tv_sec; + cu->cu_wait.tv_usec = tv->tv_usec; + break; + case CLGET_RETRY_TIMEOUT: + if (info == NULL) + return(FALSE); + *(struct timeval *)info = cu->cu_wait; + break; + case CLGET_SERVER_ADDR: + if (info == NULL) + return(FALSE); + *(struct sockaddr_in *)info = cu->cu_raddr; + break; + case CLGET_FD: + if (info == NULL) + return(FALSE); + *(int *)info = cu->cu_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + if (info == NULL) + return(FALSE); + *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1); + /* decrement by 1 as clntudp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + if (info == NULL) + return(FALSE); + *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + if (info == NULL) + return(FALSE); + *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_LOCAL_ADDR: + len = sizeof(struct sockaddr); + if (getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0) + return(FALSE); + break; + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return (FALSE); + } + return (TRUE); +} + +static void +clntudp_destroy(cl) + CLIENT *cl; +{ + register struct cu_data *cu = (struct cu_data *)cl->cl_private; + + if (cu->cu_closeit) { + (void)_close(cu->cu_sock); + } + XDR_DESTROY(&(cu->cu_outxdrs)); + mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz)); + mem_free((caddr_t)cl, sizeof(CLIENT)); +} diff --git a/c/src/exec/librpc/src/rpc/clnt_unix.c b/c/src/exec/librpc/src/rpc/clnt_unix.c index e69de29bb2..1107bc3e15 100644 --- a/c/src/exec/librpc/src/rpc/clnt_unix.c +++ b/c/src/exec/librpc/src/rpc/clnt_unix.c @@ -0,0 +1,635 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_unix.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_unix.c,v 1.5 2000/01/27 23:06:37 jasone Exp $"; +#endif + +/* + * clnt_unix.c, Implements a AF_UNIX based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * AF_UNIX based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCALL_MSG_SIZE 24 + +static int readunix(); +static int writeunix(); + +static enum clnt_stat clntunix_call(); +static void clntunix_abort(); +static void clntunix_geterr(); +static bool_t clntunix_freeres(); +static bool_t clntunix_control(); +static void clntunix_destroy(); + +static struct clnt_ops unix_ops = { + clntunix_call, + clntunix_abort, + clntunix_geterr, + clntunix_freeres, + clntunix_destroy, + clntunix_control +}; + +struct ct_data { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_un ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; +}; + +/* + * Create a client handle for a unix/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/unix package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +CLIENT * +clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) + struct sockaddr_un *raddr; + u_long prog; + u_long vers; + register int *sockp; + u_int sendsz; + u_int recvsz; +{ + CLIENT *h; + register struct ct_data *ct = NULL; + struct timeval now; + struct rpc_msg call_msg; + static u_int32_t disrupt; + int len; + + if (disrupt == 0) + disrupt = (u_int32_t)(long)raddr; + + h = (CLIENT *)mem_alloc(sizeof(*h)); + if (h == NULL) { + (void)fprintf(stderr, "clntunix_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + ct = (struct ct_data *)mem_alloc(sizeof(*ct)); + if (ct == NULL) { + (void)fprintf(stderr, "clntunix_create: out of memory\n"); + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + goto fooy; + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) { + *sockp = socket(AF_UNIX, SOCK_STREAM, 0); + len = strlen(raddr->sun_path) + sizeof(raddr->sun_family) + + sizeof(raddr->sun_len) + 1; + raddr->sun_len = len; + if ((*sockp < 0) + || (connect(*sockp, (struct sockaddr *)raddr, len) < 0)) { + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + if (*sockp != -1) + (void)_close(*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } else { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + (void)gettimeofday(&now, (struct timezone *)0); + call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec; + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, + XDR_ENCODE); + if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { + if (ct->ct_closeit) { + (void)_close(*sockp); + } + goto fooy; + } + ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); + XDR_DESTROY(&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t)ct, readunix, writeunix); + h->cl_ops = &unix_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create(); + return (h); + +fooy: + /* + * Something goofed, free stuff and barf + */ + if (ct) + mem_free((caddr_t)ct, sizeof(struct ct_data)); + if (h) + mem_free((caddr_t)h, sizeof(CLIENT)); + return ((CLIENT *)NULL); +} + +static enum clnt_stat +clntunix_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) + register CLIENT *h; + u_long proc; + xdrproc_t xdr_args; + caddr_t args_ptr; + xdrproc_t xdr_results; + caddr_t results_ptr; + struct timeval timeout; +{ + register struct ct_data *ct = (struct ct_data *) h->cl_private; + register XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */ + register bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 + && timeout.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl(--(*msg_x_id)); + if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || + (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(h->cl_auth, xdrs)) || + (! (*xdr_args)(xdrs, args_ptr))) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void)xdrrec_endofrecord(xdrs, TRUE); + return (ct->ct_error.re_status); + } + if (! xdrrec_endofrecord(xdrs, shipnow)) + return (ct->ct_error.re_status = RPC_CANTSEND); + if (! shipnow) + return (RPC_SUCCESS); + /* + * Hack to provide rpc-based message passing + */ + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { + return(ct->ct_error.re_status = RPC_TIMEDOUT); + } + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = xdr_void; + if (! xdrrec_skiprecord(xdrs)) + return (ct->ct_error.re_status); + /* now decode and validate the response header */ + if (! xdr_replymsg(xdrs, &reply_msg)) { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return (ct->ct_error.re_status); + } + if (reply_msg.rm_xid == x_id) + break; + } + + /* + * process header + */ + _seterr_reply(&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) { + if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } else if (! (*xdr_results)(xdrs, results_ptr)) { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { + xdrs->x_op = XDR_FREE; + (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH(h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return (ct->ct_error.re_status); +} + +static void +clntunix_geterr(h, errp) + CLIENT *h; + struct rpc_err *errp; +{ + register struct ct_data *ct = + (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clntunix_freeres(cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + register struct ct_data *ct = (struct ct_data *)cl->cl_private; + register XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clntunix_abort() +{ +} + + +static bool_t +clntunix_control(cl, request, info) + CLIENT *cl; + int request; + char *info; +{ + register struct ct_data *ct = (struct ct_data *)cl->cl_private; + register struct timeval *tv; + int len; + + switch (request) { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + if (info == NULL) + return(FALSE); + tv = (struct timeval *)info; + ct->ct_wait.tv_sec = tv->tv_sec; + ct->ct_wait.tv_usec = tv->tv_usec; + ct->ct_waitset = TRUE; + break; + case CLGET_TIMEOUT: + if (info == NULL) + return(FALSE); + *(struct timeval *)info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + if (info == NULL) + return(FALSE); + *(struct sockaddr_un *)info = ct->ct_addr; + break; + case CLGET_FD: + if (info == NULL) + return(FALSE); + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + if (info == NULL) + return(FALSE); + *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1); + /* decrement by 1 as clntunix_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + if (info == NULL) + return(FALSE); + *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + if (info == NULL) + return(FALSE); + *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_LOCAL_ADDR: + len = sizeof(struct sockaddr); + if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0) + return(FALSE); + break; + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return (FALSE); + } + return (TRUE); +} + + +static void +clntunix_destroy(h) + CLIENT *h; +{ + register struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) { + (void)_close(ct->ct_sock); + } + XDR_DESTROY(&(ct->ct_xdrs)); + mem_free((caddr_t)ct, sizeof(struct ct_data)); + mem_free((caddr_t)h, sizeof(CLIENT)); +} + +/* + * read() and write() are replaced with recvmsg()/sendmsg() so that + * we can pass ancillary control data. In this case, the data constists + * of credential information which the kernel will fill in for us. + * XXX: This code is specific to FreeBSD and will not work on other + * platforms without the requisite kernel modifications. + */ +struct cmessage { + struct cmsghdr cmsg; + struct cmsgcred cmcred; +}; + +static int __msgread(sock, buf, cnt) + int sock; + void *buf; + size_t cnt; +{ + struct iovec iov[1]; + struct msghdr msg; + struct cmessage cm; + + bzero((char *)&cm, sizeof(cm)); + iov[0].iov_base = buf; + iov[0].iov_len = cnt; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = (caddr_t)&cm; + msg.msg_controllen = sizeof(struct cmessage); + msg.msg_flags = 0; + + return(recvmsg(sock, &msg, 0)); +} + +static int __msgwrite(sock, buf, cnt) + int sock; + void *buf; + size_t cnt; +{ + struct iovec iov[1]; + struct msghdr msg; + struct cmessage cm; + + bzero((char *)&cm, sizeof(cm)); + iov[0].iov_base = buf; + iov[0].iov_len = cnt; + + cm.cmsg.cmsg_type = SCM_CREDS; + cm.cmsg.cmsg_level = SOL_SOCKET; + cm.cmsg.cmsg_len = sizeof(struct cmessage); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = (caddr_t)&cm; + msg.msg_controllen = sizeof(struct cmessage); + msg.msg_flags = 0; + + return(sendmsg(sock, &msg, 0)); +} + +/* + * Interface between xdr serializer and unix connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readunix(ct, buf, len) + register struct ct_data *ct; + caddr_t buf; + register int len; +{ + fd_set *fds, readfds; + struct timeval start, after, duration, delta, tmp, tv; + int r, save_errno; + + if (len == 0) + return (0); + + if (ct->ct_sock + 1 > FD_SETSIZE) { + int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask); + fds = (fd_set *)malloc(bytes); + if (fds == NULL) + return (-1); + memset(fds, 0, bytes); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + gettimeofday(&start, NULL); + delta = ct->ct_wait; + while (TRUE) { + /* XXX we know the other bits are still clear */ + FD_SET(ct->ct_sock, fds); + tv = delta; /* in case select writes back */ + r = select(ct->ct_sock+1, fds, NULL, NULL, &tv); + save_errno = errno; + + gettimeofday(&after, NULL); + timersub(&start, &after, &duration); + timersub(&delta, &duration, &tmp); + delta = tmp; + if (delta.tv_sec < 0 || !timerisset(&delta)) + r = 0; + + switch (r) { + case 0: + if (fds != &readfds) + free(fds); + ct->ct_error.re_status = RPC_TIMEDOUT; + return (-1); + + case -1: + if (errno == EINTR) + continue; + if (fds != &readfds) + free(fds); + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = save_errno; + return (-1); + } + break; + } + switch (len = __msgread(ct->ct_sock, buf, len)) { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return (len); +} + +static int +writeunix(ct, buf, len) + struct ct_data *ct; + caddr_t buf; + int len; +{ + register int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = __msgwrite(ct->ct_sock, buf, cnt)) == -1) { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return (-1); + } + } + return (len); +} diff --git a/c/src/exec/librpc/src/rpc/crypt_client.c b/c/src/exec/librpc/src/rpc/crypt_client.c index e69de29bb2..cb69470614 100644 --- a/c/src/exec/librpc/src/rpc/crypt_client.c +++ b/c/src/exec/librpc/src/rpc/crypt_client.c @@ -0,0 +1,90 @@ +/* + * 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/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef lint +static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $"; +#endif + +#ifndef KEYSERVSOCK +#define KEYSERVSOCK "/var/run/keyservsock" +#endif + +int +_des_crypt_call(buf, len, dparms) + char *buf; + int len; + struct desparams *dparms; +{ + CLIENT *clnt; + desresp *result_1; + desargs des_crypt_1_arg; + int stat; + + clnt = clnt_create(KEYSERVSOCK, CRYPT_PROG, CRYPT_VERS, "unix"); + if (clnt == (CLIENT *) NULL) { + return(DESERR_HWERROR); + } + + des_crypt_1_arg.desbuf.desbuf_len = len; + des_crypt_1_arg.desbuf.desbuf_val = buf; + des_crypt_1_arg.des_dir = dparms->des_dir; + des_crypt_1_arg.des_mode = dparms->des_mode; + bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8); + bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8); + + result_1 = des_crypt_1(&des_crypt_1_arg, clnt); + if (result_1 == (desresp *) NULL) { + clnt_destroy(clnt); + return(DESERR_HWERROR); + } + + stat = result_1->stat; + + if (result_1->stat == DESERR_NONE || + result_1->stat == DESERR_NOHWDEVICE) { + bcopy(result_1->desbuf.desbuf_val, buf, len); + bcopy(result_1->des_ivec, dparms->des_ivec, 8); + } + + clnt_freeres(clnt, xdr_desresp, (char *)result_1); + clnt_destroy(clnt); + + return(stat); +} diff --git a/c/src/exec/librpc/src/rpc/des_crypt.3 b/c/src/exec/librpc/src/rpc/des_crypt.3 index e69de29bb2..a92f577a56 100644 --- a/c/src/exec/librpc/src/rpc/des_crypt.3 +++ b/c/src/exec/librpc/src/rpc/des_crypt.3 @@ -0,0 +1,130 @@ +.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI; +.\" $FreeBSD: src/lib/libc/rpc/des_crypt.3,v 1.4 2000/03/02 09:13:45 sheldonh Exp $ +.\" +.TH DES_CRYPT 3 "6 October 1987" +.SH NAME +des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption +.SH SYNOPSIS +.nf +.B #include +.LP +.B int ecb_crypt(key, data, datalen, mode) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.LP +.B int cbc_crypt(key, data, datalen, mode, ivec) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.B char *ivec; +.LP +.B void des_setparity(key) +.B char *key; +.fi +.SH DESCRIPTION +.IX encryption cbc_crypt "" \fLcbc_crypt\fP +.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP +.IX encryption des_setparity "" \fLdes_setparity\fP +.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP +.B ecb_crypt(\|) +and +.B cbc_crypt(\|) +implement the +.SM NBS +.SM DES +(Data Encryption Standard). +These routines are faster and more general purpose than +.BR crypt (3). +They also are able to utilize +.SM DES +hardware if it is available. +.B ecb_crypt(\|) +encrypts in +.SM ECB +(Electronic Code Book) +mode, which encrypts blocks of data independently. +.B cbc_crypt(\|) +encrypts in +.SM CBC +(Cipher Block Chaining) +mode, which chains together +successive blocks. +.SM CBC +mode protects against insertions, deletions and +substitutions of blocks. +Also, regularities in the clear text will +not appear in the cipher text. +.LP +Here is how to use these routines. The first parameter, +.IR key , +is the 8-byte encryption key with parity. +To set the key's parity, which for +.SM DES +is in the low bit of each byte, use +.IR des_setparity . +The second parameter, +.IR data , +contains the data to be encrypted or decrypted. +The +third parameter, +.IR datalen , +is the length in bytes of +.IR data , +which must be a multiple of 8. The fourth parameter, +.IR mode , +is formed by +.SM OR\s0'ing +together some things. For the encryption direction 'or' in either +.SM DES_ENCRYPT +or +.SM DES_DECRYPT\s0. +For software versus hardware +encryption, 'or' in either +.SM DES_HW +or +.SM DES_SW\s0. +If +.SM DES_HW +is specified, and there is no hardware, then the encryption is performed +in software and the routine returns +.SM DESERR_NOHWDEVICE\s0. +For +.IR cbc_crypt , +the parameter +.I ivec +is the the 8-byte initialization +vector for the chaining. It is updated to the next initialization +vector upon return. +.LP +.SH "SEE ALSO" +.BR des (1), +.BR crypt (3) +.SH DIAGNOSTICS +.PD 0 +.TP 20 +.SM DESERR_NONE +No error. +.TP +.SM DESERR_NOHWDEVICE +Encryption succeeded, but done in software instead of the requested hardware. +.TP +.SM DESERR_HWERR +An error occurred in the hardware or driver. +.TP +.SM DESERR_BADPARAM +Bad parameter to routine. +.PD +.LP +Given a result status +.IR stat , +the macro +.SM DES_FAILED\c +.BR ( stat ) +is false only for the first two statuses. +.SH RESTRICTIONS +These routines are not available in RPCSRC 4.0. +This information is provided to describe the DES interface expected by +Secure RPC. diff --git a/c/src/exec/librpc/src/rpc/des_crypt.c b/c/src/exec/librpc/src/rpc/des_crypt.c index e69de29bb2..d74ce9403a 100644 --- a/c/src/exec/librpc/src/rpc/des_crypt.c +++ b/c/src/exec/librpc/src/rpc/des_crypt.c @@ -0,0 +1,153 @@ +/* + * 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 + */ +/* + * des_crypt.c, DES encryption library routines + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#include +#include +#include + +#ifndef lint +/* from: static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; */ +static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/des_crypt.c,v 1.3 1999/08/28 00:00:38 peter Exp $"; +#endif + +static int common_crypt __P(( char *, char *, register unsigned, unsigned, struct desparams * )); +int (*__des_crypt_LOCAL)() = 0; +extern _des_crypt_call __P(( char *, int, struct desparams * )); +/* + * Copy 8 bytes + */ +#define COPY8(src, dst) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +} + +/* + * Copy multiple of 8 bytes + */ +#define DESCOPY(src, dst, len) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + register int i; \ + for (i = (int) len; i > 0; i -= 8) { \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + } \ +} + +/* + * CBC mode encryption + */ +int +cbc_crypt(key, buf, len, mode, ivec) + char *key; + char *buf; + unsigned len; + unsigned mode; + char *ivec; +{ + int err; + struct desparams dp; + +#ifdef BROKEN_DES + dp.UDES.UDES_buf = buf; + dp.des_mode = ECB; +#else + dp.des_mode = CBC; +#endif + COPY8(ivec, dp.des_ivec); + err = common_crypt(key, buf, len, mode, &dp); + COPY8(dp.des_ivec, ivec); + return(err); +} + + +/* + * ECB mode encryption + */ +int +ecb_crypt(key, buf, len, mode) + char *key; + char *buf; + unsigned len; + unsigned mode; +{ + struct desparams dp; + +#ifdef BROKEN_DES + dp.UDES.UDES_buf = buf; + dp.des_mode = CBC; +#else + dp.des_mode = ECB; +#endif + return(common_crypt(key, buf, len, mode, &dp)); +} + + + +/* + * Common code to cbc_crypt() & ecb_crypt() + */ +static int +common_crypt(key, buf, len, mode, desp) + char *key; + char *buf; + register unsigned len; + unsigned mode; + register struct desparams *desp; +{ + register int desdev; + + if ((len % 8) != 0 || len > DES_MAXDATA) { + return(DESERR_BADPARAM); + } + desp->des_dir = + ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; + + desdev = mode & DES_DEVMASK; + COPY8(key, desp->des_key); + /* + * software + */ + if (__des_crypt_LOCAL != NULL) { + if (!__des_crypt_LOCAL(buf, len, desp)) { + return (DESERR_HWERROR); + } + } else { + if (!_des_crypt_call(buf, len, desp)) { + return (DESERR_HWERROR); + } + } + return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE); +} diff --git a/c/src/exec/librpc/src/rpc/des_soft.c b/c/src/exec/librpc/src/rpc/des_soft.c index e69de29bb2..01dd7f280b 100644 --- a/c/src/exec/librpc/src/rpc/des_soft.c +++ b/c/src/exec/librpc/src/rpc/des_soft.c @@ -0,0 +1,67 @@ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; +#endif +/* + * 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 + */ +/* + * Table giving odd parity in the low bit for ASCII characters + */ +static char partab[128] = { + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, +}; + +/* + * Add odd parity to low bit of 8 byte key + */ +void +des_setparity(p) + char *p; +{ + int i; + + for (i = 0; i < 8; i++) { + *p = partab[*p & 0x7f]; + p++; + } +} diff --git a/c/src/exec/librpc/src/rpc/get_myaddress.c b/c/src/exec/librpc/src/rpc/get_myaddress.c index e69de29bb2..c636ea2be9 100644 --- a/c/src/exec/librpc/src/rpc/get_myaddress.c +++ b/c/src/exec/librpc/src/rpc/get_myaddress.c @@ -0,0 +1,112 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/get_myaddress.c,v 1.17 2000/01/27 23:06:37 jasone Exp $"; +#endif + +/* + * get_myaddress.c + * + * Get client's IP address via ioctl. This avoids using the yellowpages. + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces. We return information from a loopback + * interface only if there are no other possible interfaces. + */ +int +get_myaddress(addr) + struct sockaddr_in *addr; +{ + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq ifreq, *ifr, *end; + int loopback = 0, gotit = 0; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return(-1); + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { + _close(s); + return(-1); + } +again: + ifr = ifc.ifc_req; + end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + + while (ifr < end) { + ifreq = *ifr; + if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + _close(s); + return(-1); + } + if (((ifreq.ifr_flags & IFF_UP) && + ifr->ifr_addr.sa_family == AF_INET && + !(ifreq.ifr_flags & IFF_LOOPBACK)) || + (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK) + && (ifr->ifr_addr.sa_family == AF_INET) + && (ifreq.ifr_flags & IFF_UP))) { + *addr = *((struct sockaddr_in *)&ifr->ifr_addr); + addr->sin_port = htons(PMAPPORT); + gotit = 1; + break; + } + if (ifr->ifr_addr.sa_len) + ifr = (struct ifreq *) ((caddr_t) ifr + + ifr->ifr_addr.sa_len - + sizeof(struct sockaddr)); + ifr++; + } + if (gotit == 0 && loopback == 0) { + loopback = 1; + goto again; + } + (void)_close(s); + return (gotit ? 0 : -1); +} diff --git a/c/src/exec/librpc/src/rpc/getpublickey.c b/c/src/exec/librpc/src/rpc/getpublickey.c index e69de29bb2..e1c34d9b25 100644 --- a/c/src/exec/librpc/src/rpc/getpublickey.c +++ b/c/src/exec/librpc/src/rpc/getpublickey.c @@ -0,0 +1,172 @@ +/* + * 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 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro"; +#endif + +/* + * publickey.c + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * Public key lookup routines + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PKFILE "/etc/publickey" + +/* + * Hack to let ypserv/rpc.nisd use AUTH_DES. + */ +int (*__getpublickey_LOCAL)() = 0; + +/* + * Get somebody's public key + */ +int +__getpublickey_real(netname, publickey) + char *netname; + char *publickey; +{ + char lookup[3 * HEXKEYBYTES]; + char *p; + + if (publickey == NULL) + return (0); + if (!getpublicandprivatekey(netname, lookup)) + return (0); + p = strchr(lookup, ':'); + if (p == NULL) { + return (0); + } + *p = '\0'; + (void) strncpy(publickey, lookup, HEXKEYBYTES); + publickey[HEXKEYBYTES] = '\0'; + return (1); +} + +/* + * reads the file /etc/publickey looking for a + to optionally go to the + * yellow pages + */ + +int +getpublicandprivatekey(key, ret) + char *key; + char *ret; +{ + char buf[1024]; /* big enough */ + char *res; + FILE *fd; + char *mkey; + char *mval; + + fd = fopen(PKFILE, "r"); + if (fd == (FILE *) 0) + return (0); + for (;;) { + res = fgets(buf, 1024, fd); + if (res == 0) { + fclose(fd); + return (0); + } + if (res[0] == '#') + continue; + else if (res[0] == '+') { +#ifdef YP + char *PKMAP = "publickey.byname"; + char *lookup; + char *domain; + int err; + int len; + + err = yp_get_default_domain(&domain); + if (err) { + continue; + } + lookup = NULL; + err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len); + if (err) { +#ifdef DEBUG + fprintf(stderr, "match failed error %d\n", err); +#endif + continue; + } + lookup[len] = 0; + strcpy(ret, lookup); + fclose(fd); + free(lookup); + return (2); +#else /* YP */ +#ifdef DEBUG + fprintf(stderr, +"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE); +#endif /* DEBUG */ + continue; +#endif /* YP */ + } else { + mkey = strtok(buf, "\t "); + if (mkey == NULL) { + fprintf(stderr, + "Bad record in %s -- %s", PKFILE, buf); + continue; + } + mval = strtok((char *)NULL, " \t#\n"); + if (mval == NULL) { + fprintf(stderr, + "Bad record in %s val problem - %s", PKFILE, buf); + continue; + } + if (strcmp(mkey, key) == 0) { + strcpy(ret, mval); + fclose(fd); + return (1); + } + } + } +} + +int getpublickey(netname, publickey) + char *netname; + char *publickey; +{ + if (__getpublickey_LOCAL != NULL) + return(__getpublickey_LOCAL(netname, publickey)); + else + return(__getpublickey_real(netname, publickey)); +} diff --git a/c/src/exec/librpc/src/rpc/getrpcent.3 b/c/src/exec/librpc/src/rpc/getrpcent.3 index e69de29bb2..1e92e9d03d 100644 --- a/c/src/exec/librpc/src/rpc/getrpcent.3 +++ b/c/src/exec/librpc/src/rpc/getrpcent.3 @@ -0,0 +1,98 @@ +.\" @(#)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 1999/08/28 00:00:39 peter Exp $ +.\" +.Dd December 14, 1987 +.Dt GETRPCENT 3 +.Os +.Sh NAME +.Nm getrpcent , +.Nm getrpcbyname , +.Nm getrpcbynumber , +.Nm endrpcent , +.Nm setrpcent +.Nd get RPC entry +.Sh SYNOPSIS +.Fd #include +.Ft struct rpcent * +.Fn getrpcent void +.Ft struct rpcent * +.Fn getrpcbyname "char *name" +.Ft struct rpcent * +.Fn getrpcbynumber "int number" +.Ft void +.Fn setrpcent "int stayopen" +.Ft void +.Fn endrpcent void +.Sh DESCRIPTION +The +.Fn getrpcent , +.Fn getrpcbyname , +and +.Fn getrpcbynumber +functions each return a pointer to an object with the +following structure +containing the broken-out +fields of a line in the rpc program number data base, +.Pa /etc/rpc . +.Bd -literal + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + long r_number; /* rpc program number */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width r_aliasesxxx +.It Fa r_name +The name of the server for this rpc program. +.It Fa r_aliases +A zero terminated list of alternate names for the rpc program. +.It Fa r_number +The rpc program number for this service. +.El +.Pp +The +.Fn getrpcent +function reads the next line of the file, opening the file if necessary. +The +.Nm getrpcent +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. +.Pp +.Fn endrpcent +closes the file. +.Pp +.Fn getrpcbyname +and +.Fn getrpcbynumber +sequentially search from the beginning +of the file until a matching rpc program name or +program number is found, or until end-of-file is encountered. +.Sh FILES +.Bl -tag -width /etc/rpc -compact +.It Pa /etc/rpc +.El +.Sh "SEE ALSO" +.Xr rpc 5 , +.Xr rpcinfo 8 , +.Xr ypserv 8 +.Sh DIAGNOSTICS +A +.Dv NULL +pointer is returned on +.Dv EOF +or error. +.Sh BUGS +All information +is contained in a static area +so it must be copied if it is +to be saved. diff --git a/c/src/exec/librpc/src/rpc/getrpcent.c b/c/src/exec/librpc/src/rpc/getrpcent.c index e69de29bb2..bdcf7172cb 100644 --- a/c/src/exec/librpc/src/rpc/getrpcent.c +++ b/c/src/exec/librpc/src/rpc/getrpcent.c @@ -0,0 +1,303 @@ +/* + * 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 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.10 1999/08/28 00:00:39 peter Exp $"; +#endif + +/* + * Copyright (c) 1984 by Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#ifdef YP +#include +#include +#endif + +/* + * Internet version. + */ +struct rpcdata { + FILE *rpcf; + int stayopen; +#define MAXALIASES 35 + char *rpc_aliases[MAXALIASES]; + struct rpcent rpc; + char line[BUFSIZ+1]; +#ifdef YP + char *domain; + char *current; + int currentlen; +#endif +} *rpcdata; + +#ifdef YP +static int __yp_nomap = 0; +extern int _yp_check(char **); +#endif /* YP */ + +static struct rpcent *interpret(); +struct hostent *gethostent(); +char *inet_ntoa(); + +static char RPCDB[] = "/etc/rpc"; + +static struct rpcdata * +_rpcdata() +{ + register struct rpcdata *d = rpcdata; + + if (d == 0) { + d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata)); + rpcdata = d; + } + return (d); +} + +struct rpcent * +getrpcbynumber(number) + register int number; +{ + register struct rpcdata *d = _rpcdata(); + register struct rpcent *p; +#ifdef YP + int reason; + char adrstr[16]; +#endif + + if (d == 0) + return (0); +#ifdef YP + if (!__yp_nomap && _yp_check(&d->domain)) { + sprintf(adrstr, "%d", number); + reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr), + &d->current, &d->currentlen); + switch(reason) { + case 0: + break; + case YPERR_MAP: + __yp_nomap = 1; + goto no_yp; + break; + default: + return(0); + break; + } + d->current[d->currentlen] = '\0'; + p = interpret(d->current, d->currentlen); + (void) free(d->current); + return p; + } +no_yp: +#endif /* YP */ + setrpcent(0); + while ((p = getrpcent())) { + if (p->r_number == number) + break; + } + endrpcent(); + return (p); +} + +struct rpcent * +getrpcbyname(name) + char *name; +{ + struct rpcent *rpc = NULL; + char **rp; + + setrpcent(0); + while ((rpc = getrpcent())) { + if (strcmp(rpc->r_name, name) == 0) + goto done; + for (rp = rpc->r_aliases; *rp != NULL; rp++) { + if (strcmp(*rp, name) == 0) + goto done; + } + } +done: + endrpcent(); + return (rpc); +} + +void +setrpcent(f) + int f; +{ + register struct rpcdata *d = _rpcdata(); + + if (d == 0) + return; +#ifdef YP + if (!__yp_nomap && _yp_check(NULL)) { + if (d->current) + free(d->current); + d->current = NULL; + d->currentlen = 0; + return; + } + __yp_nomap = 0; +#endif /* YP */ + if (d->rpcf == NULL) + d->rpcf = fopen(RPCDB, "r"); + else + rewind(d->rpcf); + d->stayopen |= f; +} + +void +endrpcent() +{ + register struct rpcdata *d = _rpcdata(); + + if (d == 0) + return; +#ifdef YP + if (!__yp_nomap && _yp_check(NULL)) { + if (d->current && !d->stayopen) + free(d->current); + d->current = NULL; + d->currentlen = 0; + return; + } + __yp_nomap = 0; +#endif /* YP */ + if (d->rpcf && !d->stayopen) { + fclose(d->rpcf); + d->rpcf = NULL; + } +} + +struct rpcent * +getrpcent() +{ + register struct rpcdata *d = _rpcdata(); +#ifdef YP + struct rpcent *hp; + int reason; + char *val = NULL; + int vallen; +#endif + + if (d == 0) + return(NULL); +#ifdef YP + if (!__yp_nomap && _yp_check(&d->domain)) { + if (d->current == NULL && d->currentlen == 0) { + reason = yp_first(d->domain, "rpc.bynumber", + &d->current, &d->currentlen, + &val, &vallen); + } else { + reason = yp_next(d->domain, "rpc.bynumber", + d->current, d->currentlen, + &d->current, &d->currentlen, + &val, &vallen); + } + switch(reason) { + case 0: + break; + case YPERR_MAP: + __yp_nomap = 1; + goto no_yp; + break; + default: + return(0); + break; + } + val[vallen] = '\0'; + hp = interpret(val, vallen); + (void) free(val); + return hp; + } +no_yp: +#endif /* YP */ + if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL) + return (NULL); + /* -1 so there is room to append a \n below */ + if (fgets(d->line, BUFSIZ - 1, d->rpcf) == NULL) + return (NULL); + return (interpret(d->line, strlen(d->line))); +} + +static struct rpcent * +interpret(val, len) + char *val; + int len; +{ + register struct rpcdata *d = _rpcdata(); + char *p; + register char *cp, **q; + + if (d == 0) + return (0); + (void) strncpy(d->line, val, BUFSIZ); + d->line[BUFSIZ] = '\0'; + p = d->line; + p[len] = '\n'; + if (*p == '#') + return (getrpcent()); + cp = strpbrk(p, "#\n"); + if (cp == NULL) + return (getrpcent()); + *cp = '\0'; + cp = strpbrk(p, " \t"); + if (cp == NULL) + return (getrpcent()); + *cp++ = '\0'; + /* THIS STUFF IS INTERNET SPECIFIC */ + d->rpc.r_name = d->line; + while (*cp == ' ' || *cp == '\t') + cp++; + d->rpc.r_number = atoi(cp); + q = d->rpc.r_aliases = d->rpc_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &(d->rpc_aliases[MAXALIASES - 1])) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + return (&d->rpc); +} + diff --git a/c/src/exec/librpc/src/rpc/getrpcport.3 b/c/src/exec/librpc/src/rpc/getrpcport.3 index e69de29bb2..0e9175ec12 100644 --- a/c/src/exec/librpc/src/rpc/getrpcport.3 +++ b/c/src/exec/librpc/src/rpc/getrpcport.3 @@ -0,0 +1,31 @@ +.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI +.\" $FreeBSD: src/lib/libc/rpc/getrpcport.3,v 1.6 1999/08/28 00:00:40 peter Exp $ +.\" +.Dd October 6, 1987 +.Dt GETRPCPORT 3 +.Os +.Sh NAME +.Nm getrpcport +.Nd get RPC port number +.Sh SYNOPSIS +.Ft int +.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto" +.Sh DESCRIPTION +.Fn getrpcport +returns the port number for version +.Fa versnum +of the RPC program +.Fa prognum +running on +.Fa host +and using protocol +.Fa proto . +It returns 0 if it cannot contact the portmapper, or if +.Fa prognum +is not registered. If +.Fa prognum +is registered but not with version +.Fa versnum , +it will still return a port number (for some version of the program) +indicating that the program is indeed registered. +The version mismatch will be detected upon the first call to the service. diff --git a/c/src/exec/librpc/src/rpc/getrpcport.c b/c/src/exec/librpc/src/rpc/getrpcport.c index e69de29bb2..8d17615c66 100644 --- a/c/src/exec/librpc/src/rpc/getrpcport.c +++ b/c/src/exec/librpc/src/rpc/getrpcport.c @@ -0,0 +1,63 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/ +/*static char *sccsid = "from: @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/getrpcport.c,v 1.10 1999/08/28 00:00:40 peter Exp $"; +#endif + +/* + * Copyright (c) 1985 by Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include + +int +getrpcport(host, prognum, versnum, proto) + char *host; + int prognum, versnum, proto; +{ + struct sockaddr_in addr; + struct hostent *hp; + + 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)); +} diff --git a/c/src/exec/librpc/src/rpc/key_call.c b/c/src/exec/librpc/src/rpc/key_call.c index e69de29bb2..98df0d1f95 100644 --- a/c/src/exec/librpc/src/rpc/key_call.c +++ b/c/src/exec/librpc/src/rpc/key_call.c @@ -0,0 +1,427 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + * + * $FreeBSD: src/lib/libc/rpc/key_call.c,v 1.3 2000/01/27 23:06:39 jasone Exp $ + */ + +#ident "@(#)key_call.c 1.25 94/04/24 SMI" + +/* + * key_call.c, Interface to keyserver + * + * setsecretkey(key) - set your secret key + * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent + * decryptsessionkey(agent, deskey) - decrypt ditto + * gendeskey(deskey) - generate a secure des key + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define KEY_TIMEOUT 5 /* per-try timeout in seconds */ +#define KEY_NRETRY 12 /* number of retries */ + +#ifdef DEBUG +#define debug(msg) (void) fprintf(stderr, "%s\n", msg); +#else +#define debug(msg) +#endif /* DEBUG */ + +/* + * Hack to allow the keyserver to use AUTH_DES (for authenticated + * NIS+ calls, for example). The only functions that get called + * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. + * + * The approach is to have the keyserver fill in pointers to local + * implementations of these functions, and to call those in key_call(). + */ + +cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0; +cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0; +des_block *(*__key_gendes_LOCAL)() = 0; + +static int key_call __P(( u_long, xdrproc_t, char *, xdrproc_t, char * )); + +int +key_setsecret(secretkey) + const char *secretkey; +{ + keystatus status; + + if (!key_call((u_long) KEY_SET, xdr_keybuf, (char *) secretkey, + xdr_keystatus, (char *)&status)) { + return (-1); + } + if (status != KEY_SUCCESS) { + debug("set status is nonzero"); + return (-1); + } + return (0); +} + + +/* key_secretkey_is_set() returns 1 if the keyserver has a secret key + * stored for the caller's effective uid; it returns 0 otherwise + * + * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't + * be using it, because it allows them to get the user's secret key. + */ + +int +key_secretkey_is_set(void) +{ + struct key_netstres kres; + + memset((void*)&kres, 0, sizeof (kres)); + if (key_call((u_long) KEY_NET_GET, xdr_void, (char *)NULL, + xdr_key_netstres, (char *) &kres) && + (kres.status == KEY_SUCCESS) && + (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { + /* avoid leaving secret key in memory */ + memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); + return (1); + } + return (0); +} + +int +key_encryptsession_pk(remotename, remotekey, deskey) + char *remotename; + netobj *remotekey; + des_block *deskey; +{ + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, + xdr_cryptkeyres, (char *)&res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("encrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +int +key_decryptsession_pk(remotename, remotekey, deskey) + char *remotename; + netobj *remotekey; + des_block *deskey; +{ + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, + xdr_cryptkeyres, (char *)&res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("decrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +int +key_encryptsession(remotename, deskey) + const char *remotename; + des_block *deskey; +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = (char *) remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, + xdr_cryptkeyres, (char *)&res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("encrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +int +key_decryptsession(remotename, deskey) + const char *remotename; + des_block *deskey; +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = (char *) remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, + xdr_cryptkeyres, (char *)&res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("decrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +int +key_gendes(key) + des_block *key; +{ + if (!key_call((u_long)KEY_GEN, xdr_void, (char *)NULL, + xdr_des_block, (char *)key)) { + return (-1); + } + return (0); +} + +int +key_setnet(arg) +struct netstarg *arg; +{ + keystatus status; + + + if (!key_call((u_long) KEY_NET_PUT, xdr_key_netstarg, (char *) arg, + xdr_keystatus, (char *) &status)){ + return (-1); + } + + if (status != KEY_SUCCESS) { + debug("key_setnet status is nonzero"); + return (-1); + } + return (1); +} + + +int +key_get_conv(pkey, deskey) + char *pkey; + des_block *deskey; +{ + cryptkeyres res; + + if (!key_call((u_long) KEY_GET_CONV, xdr_keybuf, pkey, + xdr_cryptkeyres, (char *)&res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("get_conv status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +struct key_call_private { + CLIENT *client; /* Client handle */ + pid_t pid; /* process-id at moment of creation */ + uid_t uid; /* user-id at last authorization */ +}; +static struct key_call_private *key_call_private_main = NULL; + +#ifdef foo +static void +key_call_destroy(void *vp) +{ + register struct key_call_private *kcp = (struct key_call_private *)vp; + + if (kcp) { + if (kcp->client) + clnt_destroy(kcp->client); + free(kcp); + } +} +#endif + +/* + * Keep the handle cached. This call may be made quite often. + */ +static CLIENT * +getkeyserv_handle(vers) +int vers; +{ + struct key_call_private *kcp = key_call_private_main; + struct timeval wait_time; + int fd; + struct sockaddr_un name; + int namelen = sizeof(struct sockaddr_un); + +#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ +#define TOTAL_TRIES 5 /* Number of tries */ + + 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; + kcp->client = NULL; + } + + /* if pid has changed, destroy client and rebuild */ + if (kcp->client != NULL && kcp->pid != getpid()) { + clnt_destroy(kcp->client); + kcp->client = NULL; + } + + if (kcp->client != NULL) { + /* if other side closed socket, build handle again */ + clnt_control(kcp->client, CLGET_FD, (char *)&fd); + if (getpeername(fd,(struct sockaddr *)&name,&namelen) == -1) { + auth_destroy(kcp->client->cl_auth); + clnt_destroy(kcp->client); + kcp->client = NULL; + } + } + + if (kcp->client != NULL) { + /* if uid has changed, build client handle again */ + if (kcp->uid != geteuid()) { + kcp->uid = geteuid(); + auth_destroy(kcp->client->cl_auth); + kcp->client->cl_auth = + authsys_create("", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) { + clnt_destroy(kcp->client); + kcp->client = NULL; + return ((CLIENT *) NULL); + } + } + /* Change the version number to the new one */ + clnt_control(kcp->client, CLSET_VERS, (void *)&vers); + return (kcp->client); + } + + if ((kcp->client == (CLIENT *) NULL)) + /* Use the AF_UNIX transport */ + kcp->client = clnt_create("/var/run/keyservsock", KEY_PROG, + vers, "unix"); + + if (kcp->client == (CLIENT *) NULL) { + return ((CLIENT *) NULL); + } + kcp->uid = geteuid(); + kcp->pid = getpid(); + kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) { + clnt_destroy(kcp->client); + kcp->client = NULL; + return ((CLIENT *) NULL); + } + + wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; + wait_time.tv_usec = 0; + (void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT, + (char *)&wait_time); + if (clnt_control(kcp->client, CLGET_FD, (char *)&fd)) + _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ + + return (kcp->client); +} + +/* returns 0 on failure, 1 on success */ + +static int +key_call(proc, xdr_arg, arg, xdr_rslt, rslt) + u_long proc; + xdrproc_t xdr_arg; + char *arg; + xdrproc_t xdr_rslt; + char *rslt; +{ + CLIENT *clnt; + struct timeval wait_time; + + if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { + cryptkeyres *res; + res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg); + *(cryptkeyres*)rslt = *res; + return (1); + } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { + cryptkeyres *res; + res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg); + *(cryptkeyres*)rslt = *res; + return (1); + } else if (proc == KEY_GEN && __key_gendes_LOCAL) { + des_block *res; + res = (*__key_gendes_LOCAL)(geteuid(), 0); + *(des_block*)rslt = *res; + return (1); + } + + if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || + (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || + (proc == KEY_GET_CONV)) + clnt = getkeyserv_handle(2); /* talk to version 2 */ + else + clnt = getkeyserv_handle(1); /* talk to version 1 */ + + if (clnt == NULL) { + return (0); + } + + wait_time.tv_sec = TOTAL_TIMEOUT; + wait_time.tv_usec = 0; + + if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, + wait_time) == RPC_SUCCESS) { + return (1); + } else { + return (0); + } +} diff --git a/c/src/exec/librpc/src/rpc/key_prot_xdr.c b/c/src/exec/librpc/src/rpc/key_prot_xdr.c index e69de29bb2..8cd6b6b067 100644 --- a/c/src/exec/librpc/src/rpc/key_prot_xdr.c +++ b/c/src/exec/librpc/src/rpc/key_prot_xdr.c @@ -0,0 +1,166 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" + +/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ + +bool_t +xdr_keystatus(register XDR *xdrs, keystatus *objp) +{ + + if (!xdr_enum(xdrs, (enum_t *)objp)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_keybuf(register XDR *xdrs, keybuf objp) +{ + + if (!xdr_opaque(xdrs, objp, HEXKEYBYTES)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_netnamestr(register XDR *xdrs, netnamestr *objp) +{ + + if (!xdr_string(xdrs, objp, MAXNETNAMELEN)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp) +{ + + if (!xdr_netnamestr(xdrs, &objp->remotename)) + return (FALSE); + if (!xdr_des_block(xdrs, &objp->deskey)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp) +{ + + if (!xdr_netnamestr(xdrs, &objp->remotename)) + return (FALSE); + if (!xdr_netobj(xdrs, &objp->remotekey)) + return (FALSE); + if (!xdr_des_block(xdrs, &objp->deskey)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp) +{ + + if (!xdr_keystatus(xdrs, &objp->status)) + return (FALSE); + switch (objp->status) { + case KEY_SUCCESS: + if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey)) + return (FALSE); + break; + } + return (TRUE); +} + +bool_t +xdr_unixcred(register XDR *xdrs, unixcred *objp) +{ + + if (!xdr_u_int(xdrs, &objp->uid)) + return (FALSE); + if (!xdr_u_int(xdrs, &objp->gid)) + return (FALSE); + if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS, + sizeof (u_int), (xdrproc_t) xdr_u_int)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_getcredres(register XDR *xdrs, getcredres *objp) +{ + + if (!xdr_keystatus(xdrs, &objp->status)) + return (FALSE); + switch (objp->status) { + case KEY_SUCCESS: + if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred)) + return (FALSE); + break; + } + return (TRUE); +} + +bool_t +xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp) +{ + + if (!xdr_keybuf(xdrs, objp->st_priv_key)) + return (FALSE); + if (!xdr_keybuf(xdrs, objp->st_pub_key)) + return (FALSE); + if (!xdr_netnamestr(xdrs, &objp->st_netname)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_key_netstres(register XDR *xdrs, key_netstres *objp) +{ + + if (!xdr_keystatus(xdrs, &objp->status)) + return (FALSE); + switch (objp->status) { + case KEY_SUCCESS: + if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet)) + return (FALSE); + break; + } + return (TRUE); +} diff --git a/c/src/exec/librpc/src/rpc/netname.c b/c/src/exec/librpc/src/rpc/netname.c index e69de29bb2..22167bee86 100644 --- a/c/src/exec/librpc/src/rpc/netname.c +++ b/c/src/exec/librpc/src/rpc/netname.c @@ -0,0 +1,136 @@ +/* + * 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 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro"; +#endif + +/* + * 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 +#include +#include +#ifdef YP +#include +#include +#endif +#include +#include +#include +#include +#include + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif +#ifndef NGROUPS +#define NGROUPS 16 +#endif + +static char *OPSYS = "unix"; + +/* + * Figure out my fully qualified network name + */ +int +getnetname(name) + char name[MAXNETNAMELEN+1]; +{ + uid_t uid; + + uid = geteuid(); + if (uid == 0) { + return (host2netname(name, (char *) NULL, (char *) NULL)); + } else { + return (user2netname(name, uid, (char *) NULL)); + } +} + + +/* + * Convert unix cred to network-name + */ +int +user2netname(netname, uid, domain) + char netname[MAXNETNAMELEN + 1]; + uid_t uid; + char *domain; +{ + char *dfltdom; + +#define MAXIPRINT (11) /* max length of printed integer */ + + if (domain == NULL) { + if (_rpc_get_default_domain(&dfltdom) != 0) { + return (0); + } + domain = dfltdom; + } + if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) { + return (0); + } + (void) sprintf(netname, "%s.%ld@%s", OPSYS, (u_long)uid, domain); + return (1); +} + + +/* + * Convert host to network-name + */ +int +host2netname(netname, host, domain) + char netname[MAXNETNAMELEN + 1]; + char *host; + char *domain; +{ + char *dfltdom; + char hostname[MAXHOSTNAMELEN+1]; + + if (domain == NULL) { + if (_rpc_get_default_domain(&dfltdom) != 0) { + return (0); + } + domain = dfltdom; + } + if (host == NULL) { + (void) gethostname(hostname, sizeof(hostname)); + host = hostname; + } + if (strlen(domain) + 1 + strlen(host) > MAXNETNAMELEN) { + return (0); + } + (void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain); + return (1); +} diff --git a/c/src/exec/librpc/src/rpc/netnamer.c b/c/src/exec/librpc/src/rpc/netnamer.c index e69de29bb2..eac9913119 100644 --- a/c/src/exec/librpc/src/rpc/netnamer.c +++ b/c/src/exec/librpc/src/rpc/netnamer.c @@ -0,0 +1,326 @@ +/* + * 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 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro"; +#endif +/* + * 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 +#include +#include +#ifdef YP +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +static char *OPSYS = "unix"; +#ifdef YP +static char *NETID = "netid.byname"; +#endif +static char *NETIDFILE = "/etc/netid"; + +static int getnetid __P(( char *, char * )); +static int _getgroups __P(( char *, gid_t * )); + +#ifndef NGROUPS +#define NGROUPS 16 +#endif + +/* + * Convert network-name into unix credential + */ +int +netname2user(netname, uidp, gidp, gidlenp, gidlist) + char netname[MAXNETNAMELEN + 1]; + uid_t *uidp; + gid_t *gidp; + int *gidlenp; + gid_t *gidlist; +{ + char *p; + int gidlen; + uid_t uid; + long luid; + struct passwd *pwd; + char val[1024]; + char *val1, *val2; + char *domain; + int vallen; + int err; + + if (getnetid(netname, val)) { + p = strtok(val, ":"); + if (p == NULL) + return (0); + *uidp = (uid_t) atol(val); + p = strtok(NULL, "\n,"); + *gidp = (gid_t) atol(p); + if (p == NULL) { + return (0); + } + gidlen = 0; + for (gidlen = 0; gidlen < NGROUPS; gidlen++) { + p = strtok(NULL, "\n,"); + if (p == NULL) + break; + gidlist[gidlen] = (gid_t) atol(p); + } + *gidlenp = gidlen; + + return (1); + } + val1 = strchr(netname, '.'); + if (val1 == NULL) + return (0); + if (strncmp(netname, OPSYS, (val1-netname))) + return (0); + val1++; + val2 = strchr(val1, '@'); + if (val2 == NULL) + return (0); + vallen = val2 - val1; + if (vallen > (1024 - 1)) + vallen = 1024 - 1; + (void) strncpy(val, val1, 1024); + val[vallen] = 0; + + err = _rpc_get_default_domain(&domain); /* change to rpc */ + if (err) + return (0); + + if (strcmp(val2 + 1, domain)) + return (0); /* wrong domain */ + + if (sscanf(val, "%ld", &luid) != 1) + return (0); + uid = luid; + + /* use initgroups method */ + pwd = getpwuid(uid); + if (pwd == NULL) + return (0); + *uidp = pwd->pw_uid; + *gidp = pwd->pw_gid; + *gidlenp = _getgroups(pwd->pw_name, gidlist); + return (1); +} + +/* + * initgroups + */ + +static int +_getgroups(uname, groups) + char *uname; + gid_t groups[NGROUPS]; +{ + gid_t ngroups = 0; + register struct group *grp; + register int i; + register int j; + int filter; + + setgrent(); + while ((grp = getgrent())) { + for (i = 0; grp->gr_mem[i]; i++) + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups == NGROUPS) { +#ifdef DEBUG + fprintf(stderr, + "initgroups: %s is in too many groups\n", uname); +#endif + goto toomany; + } + /* filter out duplicate group entries */ + filter = 0; + for (j = 0; j < ngroups; j++) + if (groups[j] == grp->gr_gid) { + filter++; + break; + } + if (!filter) + groups[ngroups++] = grp->gr_gid; + } + } +toomany: + endgrent(); + return (ngroups); +} + +/* + * Convert network-name to hostname + */ +int +netname2host(netname, hostname, hostlen) + char netname[MAXNETNAMELEN + 1]; + char *hostname; + int hostlen; +{ + int err; + char valbuf[1024]; + char *val; + char *val2; + int vallen; + char *domain; + + if (getnetid(netname, valbuf)) { + val = valbuf; + if ((*val == '0') && (val[1] == ':')) { + (void) strncpy(hostname, val + 2, hostlen); + return (1); + } + } + val = strchr(netname, '.'); + if (val == NULL) + return (0); + if (strncmp(netname, OPSYS, (val - netname))) + return (0); + val++; + val2 = strchr(val, '@'); + if (val2 == NULL) + return (0); + vallen = val2 - val; + if (vallen > (hostlen - 1)) + vallen = hostlen - 1; + (void) strncpy(hostname, val, vallen); + hostname[vallen] = 0; + + err = _rpc_get_default_domain(&domain); /* change to rpc */ + if (err) + return (0); + + if (strcmp(val2 + 1, domain)) + return (0); /* wrong domain */ + else + return (1); +} + +/* + * reads the file /etc/netid looking for a + to optionally go to the + * network information service. + */ +int +getnetid(key, ret) + char *key, *ret; +{ + char buf[1024]; /* big enough */ + char *res; + char *mkey; + char *mval; + FILE *fd; +#ifdef YP + char *domain; + int err; + char *lookup; + int len; +#endif + + fd = fopen(NETIDFILE, "r"); + if (fd == (FILE *) 0) { +#ifdef YP + res = "+"; + goto getnetidyp; +#else + return (0); +#endif + } + for (;;) { + if (fd == (FILE *) 0) + return (0); /* getnetidyp brings us here */ + res = fgets(buf, 1024, fd); + if (res == 0) { + fclose(fd); + return (0); + } + if (res[0] == '#') + continue; + else if (res[0] == '+') { +#ifdef YP + getnetidyp: + err = yp_get_default_domain(&domain); + if (err) { + continue; + } + lookup = NULL; + err = yp_match(domain, NETID, key, + strlen(key), &lookup, &len); + if (err) { +#ifdef DEBUG + fprintf(stderr, "match failed error %d\n", err); +#endif + continue; + } + lookup[len] = 0; + strcpy(ret, lookup); + free(lookup); + if (fd != NULL) + fclose(fd); + return (2); +#else /* YP */ +#ifdef DEBUG + fprintf(stderr, +"Bad record in %s '+' -- NIS not supported in this library copy\n", + NETIDFILE); +#endif + continue; +#endif /* YP */ + } else { + mkey = strtok(buf, "\t "); + if (mkey == NULL) { + fprintf(stderr, + "Bad record in %s -- %s", NETIDFILE, buf); + continue; + } + mval = strtok(NULL, " \t#\n"); + if (mval == NULL) { + fprintf(stderr, + "Bad record in %s val problem - %s", NETIDFILE, buf); + continue; + } + if (strcmp(mkey, key) == 0) { + strcpy(ret, mval); + fclose(fd); + return (1); + + } + } + } +} diff --git a/c/src/exec/librpc/src/rpc/pmap_clnt.c b/c/src/exec/librpc/src/rpc/pmap_clnt.c index e69de29bb2..955748ba10 100644 --- a/c/src/exec/librpc/src/rpc/pmap_clnt.c +++ b/c/src/exec/librpc/src/rpc/pmap_clnt.c @@ -0,0 +1,149 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_clnt.c,v 1.11 2000/01/27 23:06:39 jasone Exp $"; +#endif + +/* + * pmap_clnt.c + * Client interface to pmap rpc service. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct timeval timeout = { 5, 0 }; +static struct timeval tottimeout = { 60, 0 }; + +void clnt_perror(); + +#ifndef PORTMAPSOCK +#define PORTMAPSOCK "/var/run/portmapsock" +#endif + +/* + * Set a mapping between program,version and port. + * Calls the pmap service remotely to do the mapping. + */ +bool_t +pmap_set(program, version, protocol, port) + u_long program; + u_long version; + int protocol; + u_short port; +{ + struct sockaddr_in myaddress; + int socket = -1; + register CLIENT *client; + struct pmap parms; + bool_t rslt; + struct stat st; + + /* + * 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 (client == (CLIENT *)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"); + return (FALSE); + } + CLNT_DESTROY(client); + if (socket != -1) + (void)_close(socket); + return (rslt); +} + +/* + * Remove the mapping between program,version and port. + * Calls the pmap service remotely to do the un-mapping. + */ +bool_t +pmap_unset(program, version) + u_long program; + u_long version; +{ + struct sockaddr_in myaddress; + int socket = -1; + register CLIENT *client; + struct pmap parms; + bool_t rslt; + struct stat st; + + /* + * 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 (client == (CLIENT *)NULL) + return (FALSE); + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_port = parms.pm_prot = 0; + CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt, + tottimeout); + CLNT_DESTROY(client); + if (socket != -1) + (void)_close(socket); + return (rslt); +} diff --git a/c/src/exec/librpc/src/rpc/pmap_getmaps.c b/c/src/exec/librpc/src/rpc/pmap_getmaps.c index e69de29bb2..138e07c798 100644 --- a/c/src/exec/librpc/src/rpc/pmap_getmaps.c +++ b/c/src/exec/librpc/src/rpc/pmap_getmaps.c @@ -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 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_getmaps.c,v 1.11 2000/01/27 23:06:39 jasone Exp $"; +#endif + +/* + * pmap_getmap.c + * Client interface to pmap rpc service. + * contains pmap_getmaps, which is only tcp service involved + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NAMELEN 255 +#define MAX_BROADCAST_SIZE 1400 + +/* + * Get a copy of the current port maps. + * Calls the pmap service remotely to do get the maps. + */ +struct pmaplist * +pmap_getmaps(address) + struct sockaddr_in *address; +{ + struct pmaplist *head = (struct pmaplist *)NULL; + int socket = -1; + struct timeval minutetimeout; + register CLIENT *client; + + 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) { + clnt_perror(client, "pmap_getmaps rpc problem"); + } + CLNT_DESTROY(client); + } + if (socket != -1) + (void)_close(socket); + address->sin_port = 0; + return (head); +} diff --git a/c/src/exec/librpc/src/rpc/pmap_getport.c b/c/src/exec/librpc/src/rpc/pmap_getport.c index e69de29bb2..13b6a8bbcc 100644 --- a/c/src/exec/librpc/src/rpc/pmap_getport.c +++ b/c/src/exec/librpc/src/rpc/pmap_getport.c @@ -0,0 +1,91 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_getport.c,v 1.10 2000/01/27 23:06:40 jasone Exp $"; +#endif + +/* + * pmap_getport.c + * Client interface to pmap rpc service. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include + +static struct timeval timeout = { 5, 0 }; +static struct timeval tottimeout = { 60, 0 }; + +/* + * Find the mapped port for program,version. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +u_short +pmap_getport(address, program, version, protocol) + struct sockaddr_in *address; + u_long program; + u_long version; + u_int protocol; +{ + u_short port = 0; + int socket = -1; + register CLIENT *client; + struct pmap parms; + + address->sin_port = htons(PMAPPORT); + client = clntudp_bufcreate(address, PMAPPROG, + PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != (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){ + rpc_createerr.cf_stat = RPC_PMAPFAILURE; + clnt_geterr(client, &rpc_createerr.cf_error); + } else if (port == 0) { + rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; + } + CLNT_DESTROY(client); + } + if (socket != -1) + (void)_close(socket); + address->sin_port = 0; + return (port); +} diff --git a/c/src/exec/librpc/src/rpc/pmap_prot.c b/c/src/exec/librpc/src/rpc/pmap_prot.c index e69de29bb2..ec7ab30812 100644 --- a/c/src/exec/librpc/src/rpc/pmap_prot.c +++ b/c/src/exec/librpc/src/rpc/pmap_prot.c @@ -0,0 +1,59 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_prot.c,v 1.6 1999/08/28 00:00:42 peter Exp $"; +#endif + +/* + * pmap_prot.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + + +bool_t +xdr_pmap(xdrs, regs) + XDR *xdrs; + struct pmap *regs; +{ + + 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); +} diff --git a/c/src/exec/librpc/src/rpc/pmap_prot2.c b/c/src/exec/librpc/src/rpc/pmap_prot2.c index e69de29bb2..e29efe62c1 100644 --- a/c/src/exec/librpc/src/rpc/pmap_prot2.c +++ b/c/src/exec/librpc/src/rpc/pmap_prot2.c @@ -0,0 +1,118 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_prot2.c,v 1.7 1999/08/28 00:00:42 peter Exp $"; +#endif + +/* + * pmap_prot2.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + + +/* + * What is going on with linked lists? (!) + * First recall the link list declaration from pmap_prot.h: + * + * struct pmaplist { + * struct pmap pml_map; + * struct pmaplist *pml_map; + * }; + * + * Compare that declaration with a corresponding xdr declaration that + * is (a) pointer-less, and (b) recursive: + * + * typedef union switch (bool_t) { + * + * case TRUE: struct { + * struct pmap; + * pmaplist_t foo; + * }; + * + * case FALSE: struct {}; + * } pmaplist_t; + * + * Notice that the xdr declaration has no nxt pointer while + * the C declaration has no bool_t variable. The bool_t can be + * interpreted as ``more data follows me''; if FALSE then nothing + * follows this bool_t; if TRUE then the bool_t is followed by + * an actual struct pmap, and then (recursively) by the + * xdr union, pamplist_t. + * + * This could be implemented via the xdr_union primitive, though this + * would cause a one recursive call per element in the list. Rather than do + * that we can ``unwind'' the recursion + * into a while loop and do the union arms in-place. + * + * The head of the list is what the C programmer wishes to past around + * the net, yet is the data that the pointer points to which is interesting; + * this sounds like a job for xdr_reference! + */ +bool_t +xdr_pmaplist(xdrs, rp) + register XDR *xdrs; + register struct pmaplist **rp; +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + register int freeing = (xdrs->x_op == XDR_FREE); + register struct pmaplist **next = NULL; + + while (TRUE) { + more_elements = (bool_t)(*rp != NULL); + if (! xdr_bool(xdrs, &more_elements)) + return (FALSE); + if (! more_elements) + return (TRUE); /* we are done */ + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing) + next = &((*rp)->pml_next); + if (! xdr_reference(xdrs, (caddr_t *)rp, + (u_int)sizeof(struct pmaplist), xdr_pmap)) + return (FALSE); + rp = (freeing) ? next : &((*rp)->pml_next); + } +} diff --git a/c/src/exec/librpc/src/rpc/pmap_rmt.c b/c/src/exec/librpc/src/rpc/pmap_rmt.c index e69de29bb2..822293a00c 100644 --- a/c/src/exec/librpc/src/rpc/pmap_rmt.c +++ b/c/src/exec/librpc/src/rpc/pmap_rmt.c @@ -0,0 +1,415 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_rmt.c,v 1.15 2000/01/27 23:06:40 jasone Exp $"; +#endif + +/* + * pmap_rmt.c + * Client interface to pmap rpc service. + * remote call and broadcast service + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define MAX_BROADCAST_SIZE 1400 + +static struct timeval timeout = { 3, 0 }; + +/* + * pmapper remote-call-service interface. + * This routine is used to call the pmapper remote call service + * which will look up a service program in the port maps, and then + * remotely call that routine with the given parameters. This allows + * programs to do a lookup and call in one step. +*/ +enum clnt_stat +pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) + struct sockaddr_in *addr; + u_long prog, vers, proc; + xdrproc_t xdrargs, xdrres; + caddr_t argsp, resp; + struct timeval tout; + u_long *port_ptr; +{ + int socket = -1; + register CLIENT *client; + struct rmtcallargs a; + struct rmtcallres r; + enum clnt_stat stat; + + addr->sin_port = htons(PMAPPORT); + client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket); + if (client != (CLIENT *)NULL) { + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.args_ptr = argsp; + a.xdr_args = xdrargs; + r.port_ptr = port_ptr; + r.results_ptr = resp; + r.xdr_results = xdrres; + stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a, + xdr_rmtcallres, &r, tout); + CLNT_DESTROY(client); + } else { + stat = RPC_FAILED; + } + if (socket != -1) + (void)_close(socket); + addr->sin_port = 0; + return (stat); +} + + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rmtcall_args(xdrs, cap) + register XDR *xdrs; + register struct rmtcallargs *cap; +{ + u_int lenposition, argposition, position; + + if (xdr_u_long(xdrs, &(cap->prog)) && + xdr_u_long(xdrs, &(cap->vers)) && + xdr_u_long(xdrs, &(cap->proc))) { + lenposition = XDR_GETPOS(xdrs); + if (! xdr_u_long(xdrs, &(cap->arglen))) + return (FALSE); + argposition = XDR_GETPOS(xdrs); + if (! (*(cap->xdr_args))(xdrs, cap->args_ptr)) + return (FALSE); + position = XDR_GETPOS(xdrs); + cap->arglen = (u_long)position - (u_long)argposition; + XDR_SETPOS(xdrs, lenposition); + if (! xdr_u_long(xdrs, &(cap->arglen))) + return (FALSE); + XDR_SETPOS(xdrs, position); + return (TRUE); + } + return (FALSE); +} + +/* + * XDR remote call results + * written for XDR_DECODE direction only + */ +bool_t +xdr_rmtcallres(xdrs, crp) + register XDR *xdrs; + register struct rmtcallres *crp; +{ + caddr_t port_ptr; + + port_ptr = (caddr_t)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; + return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); + } + return (FALSE); +} + + +/* + * The following is kludged-up support for simple rpc broadcasts. + * Someday a large, complicated system will replace these trivial + * routines which only support udp/ip . + */ + +static int +getbroadcastnets(addrs, sock, buf) + struct in_addr *addrs; + int sock; /* any valid socket will do */ + char *buf; /* why allocxate more when we can use existing... */ +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct sockaddr_in *sin; + struct in_addr addr; + char *cp, *cplim; + int n, i = 0; + + ifc.ifc_len = UDPMSGSIZE; + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + perror("broadcast: ioctl (get interface configuration)"); + return (0); + } +#define max(a, b) (a > b ? a : b) +#define size(p) max((p).sa_len, sizeof(p)) + cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; + cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { + ifr = (struct ifreq *)cp; + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + ifreq = *ifr; + if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + perror("broadcast: ioctl (get interface flags)"); + continue; + } + if ((ifreq.ifr_flags & IFF_BROADCAST) && + (ifreq.ifr_flags & IFF_UP)) { + sin = (struct sockaddr_in *)&ifr->ifr_addr; +#ifdef SIOCGIFBRDADDR /* 4.3BSD */ + if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { + addr = + inet_makeaddr(inet_netof(sin->sin_addr), + INADDR_ANY); + } else { + addr = ((struct sockaddr_in*) + &ifreq.ifr_addr)->sin_addr; + } +#else /* 4.2 BSD */ + addr = inet_makeaddr(inet_netof(sin->sin_addr), + INADDR_ANY); +#endif + for (n=i-1; n>=0; n--) { + if (addr.s_addr == addrs[n].s_addr) + break; + } + if (n<0) { + addrs[i++] = addr; + } + } + } + return (i); +} + +typedef bool_t (*resultproc_t)(); + +enum clnt_stat +clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) + u_long prog; /* program number */ + u_long vers; /* version number */ + u_long proc; /* procedure number */ + xdrproc_t xargs; /* xdr routine for args */ + caddr_t argsp; /* pointer to args */ + xdrproc_t xresults; /* xdr routine for results */ + caddr_t resultsp; /* pointer to results */ + resultproc_t eachresult; /* call with each result obtained */ +{ + enum clnt_stat stat; + AUTH *unix_auth = authunix_create_default(); + XDR xdr_stream; + register XDR *xdrs = &xdr_stream; + int outlen, inlen, fromlen, nets; + register int sock; + int on = 1; + fd_set *fds = 0, readfds; /* initialized to avoid warning */ + register int i; + bool_t done = FALSE; + register u_long xid; + u_long port; + struct in_addr addrs[20]; + struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ + struct rmtcallargs a; + struct rmtcallres r; + struct rpc_msg msg; + struct timeval t, tv; + char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; + static u_int32_t disrupt; + + if (disrupt == 0) + disrupt = (u_int32_t)(long)resultsp; + + /* + * initialization: create a socket, a broadcast address, and + * preserialize the arguments into a send buffer. + */ + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("Cannot create socket for broadcast rpc"); + stat = RPC_CANTSEND; + goto done_broad; + } +#ifdef SO_BROADCAST + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { + perror("Cannot set socket option SO_BROADCAST"); + stat = RPC_CANTSEND; + goto done_broad; + } +#endif /* def SO_BROADCAST */ + if (sock + 1 > FD_SETSIZE) { + int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); + fds = (fd_set *)malloc(bytes); + if (fds == NULL) { + stat = RPC_CANTSEND; + goto done_broad; + } + memset(fds, 0, bytes); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + nets = getbroadcastnets(addrs, sock, inbuf); + memset(&baddr, 0, sizeof (baddr)); + baddr.sin_len = sizeof(struct sockaddr_in); + baddr.sin_family = AF_INET; + baddr.sin_port = htons(PMAPPORT); + baddr.sin_addr.s_addr = htonl(INADDR_ANY); + (void)gettimeofday(&t, (struct timezone *)0); + msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec; + t.tv_usec = 0; + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = PMAPPROG; + msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_proc = PMAPPROC_CALLIT; + msg.rm_call.cb_cred = unix_auth->ah_cred; + msg.rm_call.cb_verf = unix_auth->ah_verf; + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.xdr_args = xargs; + a.args_ptr = argsp; + r.port_ptr = &port; + r.xdr_results = xresults; + r.results_ptr = resultsp; + xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); + if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) { + stat = RPC_CANTENCODEARGS; + goto done_broad; + } + outlen = (int)xdr_getpos(xdrs); + xdr_destroy(xdrs); + /* + * Basic loop: broadcast a packet and wait a while for response(s). + * The response timeout grows larger per iteration. + * + * XXX This will loop about 5 times the stop. If there are + * lots of signals being received by the process it will quit + * send them all in one quick burst, not paying attention to + * the intended function of sending them slowly over half a + * minute or so + */ + for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) { + for (i = 0; i < nets; i++) { + baddr.sin_addr = addrs[i]; + if (sendto(sock, outbuf, outlen, 0, + (struct sockaddr *)&baddr, + sizeof (struct sockaddr)) != outlen) { + perror("Cannot send broadcast packet"); + stat = RPC_CANTSEND; + goto done_broad; + } + } + if (eachresult == NULL) { + stat = RPC_SUCCESS; + goto done_broad; + } + recv_again: + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = (caddr_t)&r; + msg.acpted_rply.ar_results.proc = xdr_rmtcallres; + /* XXX we know the other bits are still clear */ + FD_SET(sock, fds); + tv = t; /* for select() that copies back */ + switch (select(sock + 1, fds, NULL, NULL, &tv)) { + + case 0: /* timed out */ + stat = RPC_TIMEDOUT; + continue; + + case -1: /* some kind of error */ + if (errno == EINTR) + goto recv_again; + perror("Broadcast select problem"); + stat = RPC_CANTRECV; + goto done_broad; + + } /* end of select results switch */ + try_again: + fromlen = sizeof(struct sockaddr); + inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0, + (struct sockaddr *)&raddr, &fromlen); + if (inlen < 0) { + if (errno == EINTR) + goto try_again; + perror("Cannot receive reply to broadcast"); + stat = RPC_CANTRECV; + goto done_broad; + } + if (inlen < sizeof(u_int32_t)) + goto recv_again; + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); + if (xdr_replymsg(xdrs, &msg)) { + if ((msg.rm_xid == xid) && + (msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) { + raddr.sin_port = htons((u_short)port); + done = (*eachresult)(resultsp, &raddr); + } + /* otherwise, we just ignore the errors ... */ + } + xdrs->x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = xdr_void; + (void)xdr_replymsg(xdrs, &msg); + (void)(*xresults)(xdrs, resultsp); + xdr_destroy(xdrs); + if (done) { + stat = RPC_SUCCESS; + goto done_broad; + } else { + goto recv_again; + } + } +done_broad: + if (fds != &readfds) + free(fds); + if (sock >= 0) + (void)_close(sock); + AUTH_DESTROY(unix_auth); + return (stat); +} + diff --git a/c/src/exec/librpc/src/rpc/publickey.3 b/c/src/exec/librpc/src/rpc/publickey.3 index e69de29bb2..29094f98b2 100644 --- a/c/src/exec/librpc/src/rpc/publickey.3 +++ b/c/src/exec/librpc/src/rpc/publickey.3 @@ -0,0 +1,47 @@ +.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC +.\" $FreeBSD: src/lib/libc/rpc/publickey.3,v 1.4 2000/03/02 09:13:46 sheldonh Exp $ +.\" +.TH PUBLICKEY 3R "6 October 1987" +.SH NAME +publickey, getpublickey, getsecretkey \- get public or secret key +.SH SYNOPSIS +.nf +.B #include +.B #include +.LP +.B getpublickey(netname, publickey) +.B char netname[\s-1MAXNETNAMELEN\s0+1]; +.B char publickey[\s-1HEXKEYBYTES\s0+1]; +.LP +.B getsecretkey(netname, secretkey, passwd) +.B char netname[\s-1MAXNETNAMELEN\s0+1]; +.B char secretkey[\s-1HEXKEYBYTES\s0+1]; +.B char *passwd; +.fi +.SH DESCRIPTION +.IX "getpublickey function" "" "\fLgetpublickey()\fP function" +.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function" +These routines are used to get public and secret keys from the +.SM YP +database. +.B getsecretkey(\|) +has an extra argument, +.IR passwd , +which is used to decrypt the encrypted secret key stored in the database. +Both routines return 1 if they are successful in finding the key, 0 otherwise. +The keys are returned as +.SM NULL\s0-terminated, +hexadecimal strings. +If the password supplied to +.B getsecretkey(\|) +fails to decrypt the secret key, the routine will return 1 but the +.I secretkey +argument will be a +.SM NULL +string (``''). +.SH "SEE ALSO" +.BR publickey (5) +.LP +.I \s-1RPC\s0 Programmer's Manual +in +.TX NETP diff --git a/c/src/exec/librpc/src/rpc/publickey.5 b/c/src/exec/librpc/src/rpc/publickey.5 index e69de29bb2..9f7a325488 100644 --- a/c/src/exec/librpc/src/rpc/publickey.5 +++ b/c/src/exec/librpc/src/rpc/publickey.5 @@ -0,0 +1,38 @@ +.\" $FreeBSD: src/lib/libc/rpc/publickey.5,v 1.5 2000/03/02 09:13:46 sheldonh Exp $ +.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI; +.TH PUBLICKEY 5 "19 October 1987" +.SH NAME +publickey \- public key database +.SH SYNOPSIS +.B /etc/publickey +.SH DESCRIPTION +.LP +.B /etc/publickey +is the public key database used for secure +networking. +Each entry in +the database consists of a network user +name (which may either refer to +a user or a hostname), followed by the user's +public key (in hex +notation), a colon, and then the user's +secret key encrypted with +its login password (also in hex notation). +.LP +This file is altered either by the user through the +.BR chkey (1) +command or by the system administrator through the +.BR newkey (8) +command. +The file +.B /etc/publickey +should only contain data on the NIS master machine, where it +is converted into the +.SM NIS +database +.BR publickey.byname . +.SH SEE ALSO +.BR chkey (1), +.BR publickey (3R), +.BR newkey (8), +.BR ypupdated (8C) diff --git a/c/src/exec/librpc/src/rpc/rpc.3 b/c/src/exec/librpc/src/rpc/rpc.3 index e69de29bb2..f40b643827 100644 --- a/c/src/exec/librpc/src/rpc/rpc.3 +++ b/c/src/exec/librpc/src/rpc/rpc.3 @@ -0,0 +1,1767 @@ +.\" @(#)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 2000/03/02 09:13:47 sheldonh Exp $ +.\" +.TH RPC 3 "16 February 1988" +.SH NAME +rpc \- library routines for remote procedure calls +.SH SYNOPSIS AND 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. +.LP +Routines that are used for Secure RPC (DES authentication) are described in +.BR rpc_secure (3). +Secure RPC can be used only if DES encryption is available. +.LP +.ft B +.nf +.sp .5 +#include +.fi +.ft R +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +auth_destroy(auth) +\s-1AUTH\s0 *auth; +.fi +.ft R +.IP +A macro that destroys the authentication information associated with +.IR auth . +Destruction usually involves deallocation of private data +structures. +The use of +.I auth +is undefined after calling +.BR auth_destroy(\|) . +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authnone_create(\|) +.fi +.ft R +.IP +Create and returns an +.SM RPC +authentication handle that passes nonusable authentication +information with each remote procedure call. +This is the +default authentication used by +.SM RPC. +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authunix_create(host, uid, gid, len, aup_gids) +char *host; +int uid, gid, len, *aup.gids; +.fi +.ft R +.IP +Create and return an +.SM RPC +authentication handle that contains +.UX +authentication information. +The parameter +.I host +is the name of the machine on which the information was +created; +.I uid +is the user's user +.SM ID ; +.I gid +is the user's current group +.SM ID ; +.I len +and +.I aup_gids +refer to a counted array of groups to which the user belongs. +It is easy to impersonate a user. +.br +.if t .ne 5 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authunix_create_default(\|) +.fi +.ft R +.IP +Calls +.B authunix_create(\|) +with the appropriate parameters. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) +char *host; +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +.fi +.ft R +.IP +Call the remote procedure associated with +.IR prognum , +.IR versnum , +and +.I procnum +on the machine, +.IR host . +The parameter +.I in +is the address of the procedure's argument(s), and +.I out +is the address of where to place the result(s); +.I inproc +is used to encode the procedure's parameters, and +.I outproc +is used to decode the procedure's results. +This routine returns zero if it succeeds, or the value of +.B "enum clnt_stat" +cast to an integer if it fails. +The routine +.B clnt_perrno(\|) +is handy for translating failure statuses into messages. +.IP +Warning: calling remote procedures with this routine +uses +.SM UDP/IP +as a transport; see +.B clntudp_create(\|) +for restrictions. +You do not have control of timeouts or authentication using +this routine. +.br +.if t .ne 16 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult) +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +resultproc_t eachresult; +.fi +.ft R +.IP +Like +.BR callrpc(\|) , +except the call message is broadcast to all locally +connected broadcast nets. +Each time it receives a +response, this routine calls +.BR eachresult(\|) , +whose form is: +.IP +.RS 1i +.ft B +.nf +eachresult(out, addr) +char *out; +struct sockaddr_in *addr; +.ft R +.fi +.RE +.IP +where +.I out +is the same as +.I out +passed to +.BR clnt_broadcast(\|) , +except that the remote procedure's output is decoded there; +.I addr +points to the address of the machine that sent the results. +If +.B eachresult(\|) +returns zero, +.B clnt_broadcast(\|) +waits for more replies; otherwise it returns with appropriate +status. +.IP +Warning: broadcast sockets are limited in size to the +maximum transfer unit of the data link. +For ethernet, +this value is 1500 bytes. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +clnt_call(clnt, procnum, inproc, in, outproc, out, tout) +\s-1CLIENT\s0 *clnt; +u_long +procnum; +xdrproc_t inproc, outproc; +char *in, *out; +struct timeval tout; +.fi +.ft R +.IP +A macro that calls the remote procedure +.I procnum +associated with the client handle, +.IR clnt , +which is obtained with an +.SM RPC +client creation routine such as +.BR clnt_create(\|) . +The parameter +.I in +is the address of the procedure's argument(s), and +.I out +is the address of where to place the result(s); +.I inproc +is used to encode the procedure's parameters, and +.I outproc +is used to decode the procedure's results; +.I tout +is the time allowed for results to come back. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +clnt_destroy(clnt) +\s-1CLIENT\s0 *clnt; +.fi +.ft R +.IP +A macro that destroys the client's +.SM RPC +handle. +Destruction usually involves deallocation +of private data structures, including +.I clnt +itself. Use of +.I clnt +is undefined after calling +.BR clnt_destroy(\|) . +If the +.SM RPC +library opened the associated socket, it will close it also. +Otherwise, the socket remains open. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clnt_create(host, prog, vers, proto) +char *host; +u_long prog, vers; +char *proto; +.fi +.ft R +.IP +Generic client creation routine. +.I host +identifies the name of the remote host where the server +is located. +.I proto +indicates which kind of transport protocol to use. +The +currently supported values for this field are \(lqudp\(rq +and \(lqtcp\(rq. +Default timeouts are set, but can be modified using +.BR clnt_control(\|) . +.IP +Warning: Using +.SM UDP +has its shortcomings. Since +.SM UDP\s0-based +.SM RPC +messages can only hold up to 8 Kbytes of encoded data, +this transport cannot be used for procedures that take +large arguments or return huge results. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +bool_t +clnt_control(cl, req, info) +\s-1CLIENT\s0 *cl; +u_int req; +char *info; +.fi +.ft R +.IP +A macro used to change or retrieve various information +about a client object. +.I req +indicates the type of operation, and +.I info +is a pointer to the information. +For both +.SM UDP +and +.SM TCP\s0, +the supported values of +.I req +and their argument types and what they do are: +.IP +.nf +.ta +2.0i +2.0i +2.0i +.SM CLSET_TIMEOUT\s0 struct timeval set total timeout +.SM CLGET_TIMEOUT\s0 struct timeval get total timeout +.fi +.IP +Note: if you set the timeout using +.BR clnt_control(\|) , +the timeout parameter passed to +.B clnt_call(\|) +will be ignored in all future calls. +.IP +.nf +.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address +.fi +.br +.IP +The following operations are valid for +.SM UDP +only: +.IP +.nf +.ta +2.0i ; +2.0i ; +2.0i +.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout +.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout +.fi +.br +.IP +The retry timeout is the time that +.SM "UDP RPC" +waits for the server to reply before +retransmitting the request. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +clnt_freeres(clnt, outproc, out) +\s-1CLIENT\s0 *clnt; +xdrproc_t outproc; +char *out; +.fi +.ft R +.IP +A macro that frees any data allocated by the +.SM RPC/XDR +system when it decoded the results of an +.SM RPC +call. The +parameter +.I out +is the address of the results, and +.I outproc +is the +.SM XDR +routine describing the results. +This routine returns one if the results were successfully +freed, +and zero otherwise. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +void +clnt_geterr(clnt, errp) +\s-1CLIENT\s0 *clnt; +struct rpc_err *errp; +.fi +.ft R +.IP +A macro that copies the error structure out of the client +handle +to the structure at address +.IR errp . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +clnt_pcreateerror(s) +char *s; +.fi +.ft R +.IP +Print a message to standard error indicating +why a client +.SM RPC +handle could not be created. +The message is prepended with string +.I s +and a colon. +Used when a +.BR clnt_create(\|) , +.BR clntraw_create(\|) , +.BR clnttcp_create(\|) , +or +.B clntudp_create(\|) +call fails. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +clnt_perrno(stat) +enum clnt_stat stat; +.fi +.ft R +.IP +Print a message to standard error corresponding +to the condition indicated by +.IR stat . +Used after +.BR callrpc(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +clnt_perror(clnt, s) +\s-1CLIENT\s0 *clnt; +char *s; +.fi +.ft R +.IP +Print a message to standard error indicating why an +.SM RPC +call failed; +.I clnt +is the handle used to do the call. +The message is prepended with string +.I s +and a colon. +Used after +.BR clnt_call(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +char * +clnt_spcreateerror +char *s; +.fi +.ft R +.IP +Like +.BR clnt_pcreateerror(\|) , +except that it returns a string +instead of printing to the standard error. +.IP +Bugs: returns pointer to static data that is overwritten +on each call. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +char * +clnt_sperrno(stat) +enum clnt_stat stat; +.fi +.ft R +.IP +Take the same arguments as +.BR clnt_perrno(\|) , +but instead of sending a message to the standard error +indicating why an +.SM RPC +call failed, return a pointer to a string which contains +the message. The string ends with a +.SM NEWLINE\s0. +.IP +.B clnt_sperrno(\|) +is used instead of +.B clnt_perrno(\|) +if the program does not have a standard error (as a program +running as a server quite likely does not), or if the +programmer +does not want the message to be output with +.BR printf , +or if a message format different from that supported by +.B clnt_perrno(\|) +is to be used. +Note: unlike +.B clnt_sperror(\|) +and +.BR clnt_spcreaterror(\|) , +.B clnt_sperrno(\|) +returns pointer to static data, but the +result will not get overwritten on each call. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +char * +clnt_sperror(rpch, s) +\s-1CLIENT\s0 *rpch; +char *s; +.fi +.ft R +.IP +Like +.BR clnt_perror(\|) , +except that (like +.BR clnt_sperrno(\|) ) +it returns a string instead of printing to standard error. +.IP +Bugs: returns pointer to static data that is overwritten +on each call. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntraw_create(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +This routine creates a toy +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum . +The transport used to pass messages to the service is +actually a buffer within the process's address space, so the +corresponding +.SM RPC +server should live in the same address space; see +.BR svcraw_create(\|) . +This allows simulation of +.SM RPC +and acquisition of +.SM RPC +overheads, such as round trip times, without any +kernel interference. +This routine returns +.SM NULL +if it fails. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz) +struct sockaddr_in *addr; +u_long prognum, versnum; +int *sockp; +u_int sendsz, recvsz; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum ; +the client uses +.SM TCP/IP +as a transport. +The remote program is located at Internet +address +.IR *addr . +If +.\"The following in-line font conversion is necessary for the hyphen indicator +\fB\%addr\->sin_port\fR +is zero, then it is set to the actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.IR sockp . +Since +.SM TCP\s0-based +.SM RPC +uses buffered +.SM I/O , +the user may specify the size of the send and receive buffers +with the parameters +.I sendsz +and +.IR recvsz ; +values of zero choose suitable defaults. +This routine returns +.SM NULL +if it fails. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntudp_create(addr, prognum, versnum, wait, sockp) +struct sockaddr_in *addr; +u_long prognum, versnum; +struct timeval wait; +int *sockp; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum ; +the client uses +.SM UDP/IP +as a transport. +The remote program is located at Internet +address +.IR addr . +If +\fB\%addr\->sin_port\fR +is zero, then it is set to actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.IR sockp . +The +.SM UDP +transport resends the call message in intervals of +.B wait +time until a response is received or until the call times +out. +The total time for the call to time out is specified by +.BR clnt_call(\|) . +.IP +Warning: since +.SM UDP\s0-based +.SM RPC +messages can only hold up to 8 Kbytes +of encoded data, this transport cannot be used for procedures +that take large arguments or return huge results. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize) +struct sockaddr_in *addr; +u_long prognum, versnum; +struct timeval wait; +int *sockp; +unsigned int sendsize; +unsigned int recosize; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +on +.IR versnum ; +the client uses +.SM UDP/IP +as a transport. +The remote program is located at Internet +address +.IR addr . +If +\fB\%addr\->sin_port\fR +is zero, then it is set to actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.BR sockp . +The +.SM UDP +transport resends the call message in intervals of +.B wait +time until a response is received or until the call times +out. +The total time for the call to time out is specified by +.BR clnt_call(\|) . +.IP +This allows the user to specify the maximum packet size for sending and receiving +.SM UDP\s0-based +.SM RPC +messages. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +int +get_myaddress(addr) +struct sockaddr_in *addr; +.fi +.ft R +.IP +Stuff the machine's +.SM IP +address into +.IR *addr , +without consulting the library routines that deal with +.BR /etc/hosts . +The port number is always set to +.BR htons(\s-1PMAPPORT\s0) . +Returns zero on success, non-zero on failure. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +struct pmaplist * +pmap_getmaps(addr) +struct sockaddr_in *addr; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which returns a list of the current +.SM RPC +program-to-port mappings +on the host located at +.SM IP +address +.IR *addr . +This routine can return +.SM NULL . +The command +.RB ` "rpcinfo \-p" ' +uses this routine. +.br +.if t .ne 12 +.LP +.ft B +.nf +.sp .5 +u_short +pmap_getport(addr, prognum, versnum, protocol) +struct sockaddr_in *addr; +u_long prognum, versnum, protocol; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which returns the port number +on which waits a service that supports program number +.IR prognum , +version +.IR versnum , +and speaks the transport protocol associated with +.IR protocol . +The value of +.I protocol +is most likely +.B +.SM IPPROTO_UDP +or +.BR \s-1IPPROTO_TCP\s0 . +A return value of zero means that the mapping does not exist +or that +the +.SM RPC +system failed to contact the remote +.B portmap +service. In the latter case, the global variable +.B rpc_createerr(\|) +contains the +.SM RPC +status. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp) +struct sockaddr_in *addr; +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +struct timeval tout; +u_long *portp; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which instructs +.B portmap +on the host at +.SM IP +address +.I *addr +to make an +.SM RPC +call on your behalf to a procedure on that host. +The parameter +.I *portp +will be modified to the program's port number if the +procedure +succeeds. +The definitions of other parameters are discussed +in +.B callrpc(\|) +and +.BR clnt_call(\|) . +This procedure should be used for a \(lqping\(rq and nothing +else. +See also +.BR clnt_broadcast(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +pmap_set(prognum, versnum, protocol, port) +u_long prognum, versnum, protocol; +u_short port; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which establishes a mapping between the triple +.RI [ prognum , versnum , protocol\fR] +and +.I port +on the machine's +.B portmap +service. +The value of +.I protocol +is most likely +.B +.SM IPPROTO_UDP +or +.BR \s-1IPPROTO_TCP\s0 . +This routine returns one if it succeeds, zero otherwise. +Automatically done by +.BR svc_register(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +pmap_unset(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which destroys all mapping between the triple +.RI [ prognum , versnum , *\fR] +and +.B ports +on the machine's +.B portmap +service. +This routine returns one if it succeeds, zero +otherwise. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +registerrpc(prognum, versnum, procnum, procname, inproc, outproc) +u_long prognum, versnum, procnum; +char *(*procname) (\|) ; +xdrproc_t inproc, outproc; +.fi +.ft R +.IP +Register procedure +.I procname +with the +.SM RPC +service package. If a request arrives for program +.IR prognum , +version +.IR versnum , +and procedure +.IR procnum , +.I procname +is called with a pointer to its parameter(s); +.I progname +should return a pointer to its static result(s); +.I inproc +is used to decode the parameters while +.I outproc +is used to encode the results. +This routine returns zero if the registration succeeded, \-1 +otherwise. +.IP +Warning: remote procedures registered in this form +are accessed using the +.SM UDP/IP +transport; see +.B svcudp_create(\|) +for restrictions. +.br +.if t .ne 5 +.LP +.ft B +.nf +.sp .5 +struct rpc_createerr rpc_createerr; +.fi +.ft R +.IP +A global variable whose value is set by any +.SM RPC +client creation routine +that does not succeed. Use the routine +.B clnt_pcreateerror(\|) +to print the reason why. +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +svc_destroy(xprt) +\s-1SVCXPRT\s0 * +xprt; +.fi +.ft R +.IP +A macro that destroys the +.SM RPC +service transport handle, +.IR xprt . +Destruction usually involves deallocation +of private data structures, including +.I xprt +itself. Use of +.I xprt +is undefined after calling this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +fd_set svc_fdset; +.fi +.ft R +.IP +A global variable reflecting the +.SM RPC +service side's +read file descriptor bit mask; it is suitable as a template parameter +to the +.B select +system call. +This is only of interest +if a service implementor does not call +.BR svc_run(\|) , +but rather does his own asynchronous event processing. +This variable is read-only (do not pass its address to +.BR select !), +yet it may change after calls to +.B svc_getreqset(\|) +or any creation routines. +.br +As well, note that if the process has descriptor limits +which are extended beyond +.BR FD_SETSIZE , +this variable will only be usable for the first +.BR FD_SETSIZE +descriptors. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +int svc_fds; +.fi +.ft R +.IP +Similar to +.BR svc_fedset(\|) , +but limited to 32 descriptors. +This +interface is obsoleted by +.BR svc_fdset(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_freeargs(xprt, inproc, in) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t inproc; +char *in; +.fi +.ft R +.IP +A macro that frees any data allocated by the +.SM RPC/XDR +system when it decoded the arguments to a service procedure +using +.BR svc_getargs(\|) . +This routine returns 1 if the results were successfully +freed, +and zero otherwise. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +svc_getargs(xprt, inproc, in) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t inproc; +char *in; +.fi +.ft R +.IP +A macro that decodes the arguments of an +.SM RPC +request +associated with the +.SM RPC +service transport handle, +.IR xprt . +The parameter +.I in +is the address where the arguments will be placed; +.I inproc +is the +.SM XDR +routine used to decode the arguments. +This routine returns one if decoding succeeds, and zero +otherwise. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +struct sockaddr_in * +svc_getcaller(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +The approved way of getting the network address of the caller +of a procedure associated with the +.SM RPC +service transport handle, +.IR xprt . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_getreqset(rdfds) +fd_set *rdfds; +.fi +.ft R +.IP +This routine is only of interest if a service implementor +does not call +.BR svc_run(\|) , +but instead implements custom asynchronous event processing. +It is called when the +.B select +system call has determined that an +.SM RPC +request has arrived on some +.SM RPC +.B socket(s) ; +.I rdfds +is the resultant read file descriptor bit mask. +The routine returns when all sockets associated with the +value of +.I rdfds +have been serviced. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +svc_getreq(rdfds) +int rdfds; +.fi +.ft R +.IP +Similar to +.BR svc_getreqset(\|) , +but limited to 32 descriptors. +This interface is obsoleted by +.BR svc_getreqset(\|) . +.br +.if t .ne 17 +.LP +.ft B +.nf +.sp .5 +svc_register(xprt, prognum, versnum, dispatch, protocol) +\s-1SVCXPRT\s0 *xprt; +u_long prognum, versnum; +void (*dispatch) (\|); +u_long protocol; +.fi +.ft R +.IP +Associates +.I prognum +and +.I versnum +with the service dispatch procedure, +.IR dispatch . +If +.I protocol +is zero, the service is not registered with the +.B portmap +service. If +.I protocol +is non-zero, then a mapping of the triple +.RI [ prognum , versnum , protocol\fR] +to +\fB\%xprt\->xp_port\fR +is established with the local +.B portmap +service (generally +.I protocol +is zero, +.B +.SM IPPROTO_UDP +or +.B +.SM IPPROTO_TCP +). +The procedure +.I dispatch +has the following form: +.RS 1i +.ft B +.nf +dispatch(request, xprt) +struct svc_req *request; +\s-1SVCXPRT\s0 *xprt; +.ft R +.fi +.RE +.IP +The +.B svc_register(\|) +routine returns one if it succeeds, and zero otherwise. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +svc_run(\|) +.fi +.ft R +.IP +This routine never returns. +It waits for +.SM RPC +requests to arrive, and calls the appropriate service +procedure using +.B svc_getreq(\|) +when one arrives. +This procedure is usually waiting for a +.B select(\|) +system call to return. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_sendreply(xprt, outproc, out) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t outproc; +char *out; +.fi +.ft R +.IP +Called by an +.SM RPC +service's dispatch routine to send the results of a +remote procedure call. The parameter +.I xprt +is the request's associated transport handle; +.I outproc +is the +.SM XDR +routine which is used to encode the results; and +.I out +is the address of the results. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svc_unregister(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +Remove all mapping of the double +.RI [ prognum , versnum ] +to dispatch routines, and of the triple +.RI [ prognum , versnum , *\fR] +to port number. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +void +svcerr_auth(xprt, why) +\s-1SVCXPRT\s0 *xprt; +enum auth_stat why; +.fi +.ft R +.IP +Called by a service dispatch routine that refuses to perform +a remote procedure call due to an authentication error. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_decode(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that cannot successfully +decode its parameters. +See also +.BR svc_getargs(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_noproc(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that does not implement +the procedure number that the caller requests. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_noprog(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called when the desired program is not registered with the +.SM RPC +package. +Service implementors usually do not need this routine. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_progvers(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called when the desired version of a program is not registered +with the +.SM RPC +package. +Service implementors usually do not need this routine. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_systemerr(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine when it detects a system +error +not covered by any particular protocol. +For example, if a service can no longer allocate storage, +it may call this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +svcerr_weakauth(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that refuses to perform +a remote procedure call due to insufficient +authentication parameters. The routine calls +.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" . +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcraw_create(\|) +.fi +.ft R +.IP +This routine creates a toy +.SM RPC +service transport, to which it returns a pointer. The +transport +is really a buffer within the process's address space, +so the corresponding +.SM RPC +client should live in the same +address space; +see +.BR clntraw_create(\|) . +This routine allows simulation of +.SM RPC +and acquisition of +.SM RPC +overheads (such as round trip times), without any kernel +interference. +This routine returns +.SM NULL +if it fails. +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svctcp_create(sock, send_buf_size, recv_buf_size) +int sock; +u_int send_buf_size, recv_buf_size; +.fi +.ft R +.IP +This routine creates a +.SM TCP/IP\s0-based +.SM RPC +service transport, to which it returns a pointer. +The transport is associated with the socket +.IR sock , +which may be +.BR \s-1RPC_ANYSOCK\s0 , +in which case a new socket is created. +If the socket is not bound to a local +.SM TCP +port, then this routine binds it to an arbitrary port. Upon +completion, +\fB\%xprt\->xp_sock\fR +is the transport's socket descriptor, and +\fB\%xprt\->xp_port\fR +is the transport's port number. +This routine returns +.SM NULL +if it fails. +Since +.SM TCP\s0-based +.SM RPC +uses buffered +.SM I/O , +users may specify the size of buffers; values of zero +choose suitable defaults. +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcfd_create(fd, sendsize, recvsize) +int fd; +u_int sendsize; +u_int recvsize; +.fi +.ft R +.IP +Create a service on top of any open descriptor. +Typically, +this +descriptor is a connected socket for a stream protocol such +as +.SM TCP\s0. +.I sendsize +and +.I recvsize +indicate sizes for the send and receive buffers. If they are +zero, a reasonable default is chosen. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcudp_bufcreate(sock, sendsize, recosize) +int sock; +.fi +.ft R +.IP +This routine creates a +.SM UDP/IP\s0-based +.SM RPC +service transport, to which it returns a pointer. +The transport is associated with the socket +.IR sock , +which may be +.B \s-1RPC_ANYSOCK\s0 , +in which case a new socket is created. +If the socket is not bound to a local +.SM UDP +port, then this routine binds it to an arbitrary port. +Upon +completion, +\fB\%xprt\->xp_sock\fR +is the transport's socket descriptor, and +\fB\%xprt\->xp_port\fR +is the transport's port number. +This routine returns +.SM NULL +if it fails. +.IP +This allows the user to specify the maximum packet size for sending and +receiving +.SM UDP\s0-based +.SM RPC messages. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_accepted_reply(xdrs, ar) +\s-1XDR\s0 *xdrs; +struct accepted_reply *ar; +.fi +.ft R +.IP +Used for encoding +.SM RPC +reply messages. +This routine is useful for users who +wish to generate +\s-1RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_authunix_parms(xdrs, aupp) +\s-1XDR\s0 *xdrs; +struct authunix_parms *aupp; +.fi +.ft R +.IP +Used for describing +.SM UNIX +credentials. +This routine is useful for users +who wish to generate these credentials without using the +.SM RPC +authentication package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +xdr_callhdr(xdrs, chdr) +\s-1XDR\s0 *xdrs; +struct rpc_msg *chdr; +.fi +.ft R +.IP +Used for describing +.SM RPC +call header messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_callmsg(xdrs, cmsg) +\s-1XDR\s0 *xdrs; +struct rpc_msg *cmsg; +.fi +.ft R +.IP +Used for describing +.SM RPC +call messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_opaque_auth(xdrs, ap) +\s-1XDR\s0 *xdrs; +struct opaque_auth *ap; +.fi +.ft R +.IP +Used for describing +.SM RPC +authentication information messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_pmap(xdrs, regs) +\s-1XDR\s0 *xdrs; +struct pmap *regs; +.fi +.ft R +.IP +Used for describing parameters to various +.B portmap +procedures, externally. +This routine is useful for users who wish to generate +these parameters without using the +.B pmap +interface. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_pmaplist(xdrs, rp) +\s-1XDR\s0 *xdrs; +struct pmaplist **rp; +.fi +.ft R +.IP +Used for describing a list of port mappings, externally. +This routine is useful for users who wish to generate +these parameters without using the +.B pmap +interface. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_rejected_reply(xdrs, rr) +\s-1XDR\s0 *xdrs; +struct rejected_reply *rr; +.fi +.ft R +.IP +Used for describing +.SM RPC +reply messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_replymsg(xdrs, rmsg) +\s-1XDR\s0 *xdrs; +struct rpc_msg *rmsg; +.fi +.ft R +.IP +Used for describing +.SM RPC +reply messages. +This routine is useful for users who wish to generate +.SM RPC +style messages without using the +.SM RPC +package. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +xprt_register(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +After +.SM RPC +service transport handles are created, +they should register themselves with the +.SM RPC +service package. +This routine modifies the global variable +.BR svc_fds(\|) . +Service implementors usually do not need this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +xprt_unregister(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Before an +.SM RPC +service transport handle is destroyed, +it should unregister itself with the +.SM RPC +service package. +This routine modifies the global variable +.BR svc_fds(\|) . +Service implementors usually do not need this routine. +.SH SEE ALSO +.BR rpc_secure (3), +.BR xdr (3) +.br +The following manuals: +.RS +.ft I +Remote Procedure Calls: Protocol Specification +.br +Remote Procedure Call Programming Guide +.br +rpcgen Programming Guide +.br +.ft R +.RE +.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" , +.SM RFC1050, Sun Microsystems, Inc., +.SM USC-ISI\s0. + diff --git a/c/src/exec/librpc/src/rpc/rpc.5 b/c/src/exec/librpc/src/rpc/rpc.5 index e69de29bb2..36f895dbf2 100644 --- a/c/src/exec/librpc/src/rpc/rpc.5 +++ b/c/src/exec/librpc/src/rpc/rpc.5 @@ -0,0 +1,35 @@ +.\" $FreeBSD: src/lib/libc/rpc/rpc.5,v 1.6 1999/08/28 00:00:44 peter Exp $ +.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI; +.Dd September 26, 1985 +.Dt RPC 5 +.Sh NAME +.Nm rpc +.Nd rpc program number data base +.Sh SYNOPSIS +/etc/rpc +.Sh DESCRIPTION +The +.Pa /etc/rpc +file contains user readable names that +can be used in place of rpc program numbers. +Each line has the following information: +.Pp +.Bl -bullet -compact +.It +name of server for the rpc program +.It +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 +the line are not interpreted by routines which search the file. +.Sh FILES +.Bl -tag -compact -width /etc/rpc +.Pa /etc/rpc +.El +.Sh "SEE ALSO" +.Xr getrpcent 3 diff --git a/c/src/exec/librpc/src/rpc/rpc_callmsg.c b/c/src/exec/librpc/src/rpc/rpc_callmsg.c index e69de29bb2..982fc47b45 100644 --- a/c/src/exec/librpc/src/rpc/rpc_callmsg.c +++ b/c/src/exec/librpc/src/rpc/rpc_callmsg.c @@ -0,0 +1,193 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_callmsg.c,v 1.9 1999/08/28 00:00:45 peter Exp $"; +#endif + +/* + * rpc_callmsg.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#include +#include +#include +#include + +/* + * XDR a call message + */ +bool_t +xdr_callmsg(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + register int32_t *buf; + register struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) { + IXDR_PUT_LONG(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); + 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); + oa = &cmsg->rm_call.cb_cred; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { + memcpy((caddr_t)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); + if (oa->oa_length) { + memcpy((caddr_t)buf, oa->oa_base, oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / sizeof (int32_t); + */ + } + return (TRUE); + } + } + if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) { + cmsg->rm_xid = IXDR_GET_LONG(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); + 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); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(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); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + memcpy(oa->oa_base, (caddr_t)buf, + oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / + sizeof (int32_t); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int(xdrs, &oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(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); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + memcpy(oa->oa_base, (caddr_t)buf, + oa->oa_length); + /* no real need... + buf += RNDUP(oa->oa_length) / + sizeof (int32_t); + */ + } + } + return (TRUE); + } + } + if ( + xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) ) + return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); + return (FALSE); +} + diff --git a/c/src/exec/librpc/src/rpc/rpc_commondata.c b/c/src/exec/librpc/src/rpc/rpc_commondata.c index e69de29bb2..bbe6003337 100644 --- a/c/src/exec/librpc/src/rpc/rpc_commondata.c +++ b/c/src/exec/librpc/src/rpc/rpc_commondata.c @@ -0,0 +1,41 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_commondata.c,v 1.7 1999/08/28 00:00:45 peter Exp $"; +#endif + +#include +/* + * This file should only contain common data (global data) that is exported + * by public interfaces + */ +struct opaque_auth _null_auth; +struct rpc_createerr rpc_createerr; diff --git a/c/src/exec/librpc/src/rpc/rpc_dtablesize.c b/c/src/exec/librpc/src/rpc/rpc_dtablesize.c index e69de29bb2..e07c0b6568 100644 --- a/c/src/exec/librpc/src/rpc/rpc_dtablesize.c +++ b/c/src/exec/librpc/src/rpc/rpc_dtablesize.c @@ -0,0 +1,61 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/ +/*static char *sccsid = "from: @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_dtablesize.c,v 1.10 1999/08/28 00:00:45 peter Exp $"; +#endif + +#include +#include + +/* + * Cache the result of getdtablesize(), so we don't have to do an + * expensive system call every time. + */ +/* + * XXX In FreeBSD 2.x, you can have the maximum number of open file + * descriptors be greater than FD_SETSIZE (which us 256 by default). + * + * Since old programs tend to use this call to determine the first arg + * for select(), having this return > FD_SETSIZE is a Bad Idea(TM)! + */ +int +_rpc_dtablesize(void) +{ + static int size; + + if (size == 0) { + size = getdtablesize(); + if (size > FD_SETSIZE) + size = FD_SETSIZE; + } + return (size); +} diff --git a/c/src/exec/librpc/src/rpc/rpc_prot.c b/c/src/exec/librpc/src/rpc/rpc_prot.c index e69de29bb2..14a2524c70 100644 --- a/c/src/exec/librpc/src/rpc/rpc_prot.c +++ b/c/src/exec/librpc/src/rpc/rpc_prot.c @@ -0,0 +1,297 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_prot.c,v 1.8 1999/08/28 00:00:46 peter Exp $"; +#endif + +/* + * rpc_prot.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements the rpc message definition, + * its serializer and some common rpc utility routines. + * The routines are meant for various implementations of rpc - + * they are NOT for the rpc client or rpc service implementations! + * Because authentication stuff is easy and is part of rpc, the opaque + * routines are also in this program. + */ + +#include + +#include + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +struct opaque_auth _null_auth; + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth(xdrs, ap) + register XDR *xdrs; + register struct opaque_auth *ap; +{ + + if (xdr_enum(xdrs, &(ap->oa_flavor))) + return (xdr_bytes(xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES)); + return (FALSE); +} + +/* + * XDR a DES block + */ +bool_t +xdr_des_block(xdrs, blkp) + register XDR *xdrs; + register des_block *blkp; +{ + return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); +} + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +bool_t +xdr_accepted_reply(xdrs, ar) + register XDR *xdrs; + register struct accepted_reply *ar; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) + return (FALSE); + if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) + return (FALSE); + switch (ar->ar_stat) { + + case SUCCESS: + return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); + + case PROG_MISMATCH: + if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) + return (FALSE); + return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); + default: + break; + } + return (TRUE); /* TRUE => open ended set of problems */ +} + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply(xdrs, rr) + register XDR *xdrs; + register struct rejected_reply *rr; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) + return (FALSE); + switch (rr->rj_stat) { + + case RPC_MISMATCH: + if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) + return (FALSE); + return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); + + case AUTH_ERROR: + return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); + } + return (FALSE); +} + +static struct xdr_discrim reply_dscrm[3] = { + { (int)MSG_ACCEPTED, xdr_accepted_reply }, + { (int)MSG_DENIED, xdr_rejected_reply }, + { __dontcare__, NULL_xdrproc_t } }; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg(xdrs, rmsg) + register XDR *xdrs; + register struct rpc_msg *rmsg; +{ + if ( + xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY) ) + return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), + (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); + return (FALSE); +} + + +/* + * Serializes the "static part" of a call message header. + * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. + * The rm_xid is not really static, but the user can easily munge on the fly. + */ +bool_t +xdr_callhdr(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) + return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); + return (FALSE); +} + +/* ************************** Client utility routine ************* */ + +static void +accepted(acpt_stat, error) + register enum accept_stat acpt_stat; + register struct rpc_err *error; +{ + + switch (acpt_stat) { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* 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; +} + +static void +rejected(rjct_stat, error) + register enum reject_stat rjct_stat; + register struct rpc_err *error; +{ + + switch (rjct_stat) { + + case RPC_VERSMISMATCH: + 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 ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)MSG_DENIED; + error->re_lb.s2 = (long)rjct_stat; +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply(msg, error) + register struct rpc_msg *msg; + register struct rpc_err *error; +{ + + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) { + + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) { + error->re_status = RPC_SUCCESS; + return; + }; + accepted(msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected(msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + default: + break; + } +} diff --git a/c/src/exec/librpc/src/rpc/rpc_secure.3 b/c/src/exec/librpc/src/rpc/rpc_secure.3 index e69de29bb2..4efd9b8614 100644 --- a/c/src/exec/librpc/src/rpc/rpc_secure.3 +++ b/c/src/exec/librpc/src/rpc/rpc_secure.3 @@ -0,0 +1,254 @@ +.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI +.\" $FreeBSD: src/lib/libc/rpc/rpc_secure.3,v 1.6 2000/03/02 09:13:48 sheldonh Exp $ +.\" +.Dd February 16, 1988 +.Dt RPC 3 +.Sh NAME +.Nm rpc_secure +.Nd library routines for secure remote procedure calls +.Sh SYNOPSIS +.Fd #include +.Ft AUTH * +.Fo authdes_create +.Fa "char *name" +.Fa "unsigned window" +.Fa "struct sockaddr *addr" +.Fa "des_block *ckey" +.Fc +.Ft int +.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups" +.Ft int +.Fn getnetname "char *name" +.Ft int +.Fn host2netname "char *name" "char *host" "char *domain" +.Ft int +.Fn key_decryptsession "const char *remotename" "des_block *deskey" +.Ft int +.Fn key_encryptsession "const char *remotename" "des_block *deskey" +.Ft int +.Fn key_gendes "des_block *deskey" +.Ft int +.Fn key_setsecret "const char *key" +.Ft int +.Fn netname2host "char *name" "char *host" "int hostlen" +.Ft int +.Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist" +.Ft int +.Fn user2netname "char *name" "uid_t uid" "char *domain" +.Sh DESCRIPTION +These routines are part of the +.Tn RPC +library. They implement +.Tn DES +Authentication. See +.Xr rpc 3 +for further details about +.Tn RPC . +.Pp +The +.Fn authdes_create +is the first of two routines which interface to the +.Tn RPC +secure authentication system, known as +.Tn DES +authentication. +The second is +.Fn authdes_getucred , +below. +.Pp +Note: the keyserver daemon +.Xr keyserv 8 +must be running for the +.Tn DES +authentication system to work. +.Pp +.Fn Authdes_create , +used on the client side, returns an authentication handle that +will enable the use of the secure authentication system. +The first parameter +.Fa name +is the network name, or +.Fa netname , +of the owner of the server process. +This field usually +represents a +.Fa hostname +derived from the utility routine +.Fn host2netname , +but could also represent a user name using +.Fn user2netname . +The second field is window on the validity of +the client credential, given in seconds. A small +window is more secure than a large one, but choosing +too small of a window will increase the frequency of +resynchronizations because of clock drift. +The third +parameter +.Fa addr +is optional. If it is +.Dv NULL , +then the authentication system will assume +that the local clock is always in sync with the server's +clock, and will not attempt resynchronizations. +If an address +is supplied, however, then the system will use the address +for consulting the remote time service whenever +resynchronization +is required. +This parameter is usually the +address of the +.Tn RPC +server itself. +The final parameter +.Fa ckey +is also optional. If it is +.Dv NULL , +then the authentication system will +generate a random +.Tn DES +key to be used for the encryption of credentials. +If it is supplied, however, then it will be used instead. +.Pp +.Fn Authdes_getucred , +the second of the two +.Tn DES +authentication routines, +is used on the server side for converting a +.Tn DES +credential, which is +operating system independent, into a +.Ux +credential. +This routine differs from utility routine +.Fn netname2user +in that +.Fn authdes_getucred +pulls its information from a cache, and does not have to do a +Yellow Pages lookup every time it is called to get its information. +.Pp +.Fn Getnetname +installs the unique, operating-system independent netname of +the +caller in the fixed-length array +.Fa name . +Returns +.Dv TRUE +if it succeeds and +.Dv FALSE +if it fails. +.Pp +.Fn Host2netname +converts from a domain-specific hostname to an +operating-system independent netname. +Returns +.Dv TRUE +if it succeeds and +.Dv FALSE +if it fails. +Inverse of +.Fn netname2host . +.Pp +.Fn Key_decryptsession +is an interface to the keyserver daemon, which is associated +with +.Tn RPC Ns 's +secure authentication system ( +.Tn DES +authentication). +User programs rarely need to call it, or its associated routines +.Fn key_encryptsession , +.Fn key_gendes +and +.Fn key_setsecret . +System commands such as +.Xr login 1 +and the +.Tn RPC +library are the main clients of these four routines. +.Pp +.Fn Key_decryptsession +takes a server netname and a +.Tn DES +key, and decrypts the key by +using the the public key of the the server and the secret key +associated with the effective uid of the calling process. It +is the inverse of +.Fn key_encryptsession . +.Pp +.Fn Key_encryptsession +is a keyserver interface routine. +It +takes a server netname and a des key, and encrypts +it using the public key of the the server and the secret key +associated with the effective uid of the calling process. It +is the inverse of +.Fn key_decryptsession . +.Pp +.Fn Key_gendes +is a keyserver interface routine. +It +is used to ask the keyserver for a secure conversation key. +Choosing one +.Qq random +is usually not good enough, +because +the common ways of choosing random numbers, such as using the +current time, are very easy to guess. +.Pp +.Fn Key_setsecret +is a keyserver interface routine. +It is used to set the key for +the effective +.Fa uid +of the calling process. +.Pp +.Fn Netname2host +converts from an operating-system independent netname to a +domain-specific hostname. +Returns +.Dv TRUE +if it succeeds and +.Dv FALSE +if it fails. Inverse of +.Fn host2netname . +.Pp +.Fn Netname2user +converts from an operating-system independent netname to a +domain-specific user ID. +Returns +.Dv TRUE +if it succeeds and +.Dv FALSE +if it fails. +Inverse of +.Fn user2netname . +.Pp +.Fn User2netname +converts from a domain-specific username to an operating-system +independent netname. +Returns +.Dv TRUE +if it succeeds and +.Dv FALSE +if it fails. +Inverse of +.Fn netname2user . +.Sh SEE ALSO +.Xr rpc 3 , +.Xr xdr 3 , +.Xr keyserv 8 +.Pp +The following manuals: +.Rs +.%B Remote Procedure Calls: Protocol Specification +.Re +.Rs +.%B Remote Procedure Call Programming Guide +.Re +.Rs +.%B Rpcgen Programming Guide +.Re +.Rs +.%B RPC: Remote Procedure Call Protocol Specification +.%O RFC1050, Sun Microsystems Inc., USC-ISI +.Re diff --git a/c/src/exec/librpc/src/rpc/rpcdname.c b/c/src/exec/librpc/src/rpc/rpcdname.c index e69de29bb2..39f7167bcd 100644 --- a/c/src/exec/librpc/src/rpc/rpcdname.c +++ b/c/src/exec/librpc/src/rpc/rpcdname.c @@ -0,0 +1,78 @@ +/* + * 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 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro"; +#endif + +/* + * rpcdname.c + * Gets the default domain name + */ + +#include +#include +#include +#include + +#define default_domain ((char *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->rpcdname_default_domain) + +static char * +get_default_domain() +{ + char temp[256]; + + if (default_domain) + return (default_domain); + if (getdomainname(temp, sizeof(temp)) < 0) + return (0); + if ((int) strlen(temp) > 0) { + default_domain = (char *)malloc((strlen(temp)+(unsigned)1)); + if (default_domain == 0) + return (0); + (void) strcpy(default_domain, temp); + return (default_domain); + } + return (0); +} + +/* + * This is a wrapper for the system call getdomainname which returns a + * ypclnt.h error code in the failure case. It also checks to see that + * the domain name is non-null, knowing that the null string is going to + * get rejected elsewhere in the NIS client package. + */ +int +_rpc_get_default_domain(domain) + char **domain; +{ + if ((*domain = get_default_domain()) != 0) + return (0); + return (-1); +} diff --git a/c/src/exec/librpc/src/rpc/rstat.1 b/c/src/exec/librpc/src/rpc/rstat.1 index e69de29bb2..6cc47c26c8 100644 --- a/c/src/exec/librpc/src/rpc/rstat.1 +++ b/c/src/exec/librpc/src/rpc/rstat.1 @@ -0,0 +1,58 @@ +.\" $FreeBSD: src/lib/libc/rpc/rstat.1,v 1.5 1999/08/28 00:00:46 peter Exp $ +.\" @(#)rstat.1 2.1 88/08/03 4.0 RPCSRC +.TH RSTAT 1 "3 August 1988" +.SH NAME +rstat \- remote status display +.SH SYNOPSIS +.B rstat +.B host +.SH DESCRIPTION +.LP +.B rstat +displays a summary of the current system status of a particular +.BR host . +The output shows the current time of day, how long the system has +been up, +and the load averages. +The load average numbers give the number of jobs in the run queue +averaged over 1, 5 and 15 minutes. +.PP +The +.B rstat_svc(8) +daemon must be running on the remote host for this command to +work. +.B rstat +uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x. +.SH EXAMPLE +.RS +.ft B +.nf +example% rstat otherhost +7:36am up 6 days, 16:45, load average: 0.20, 0.23, 0.18 +example% +.ft R +.fi +.RE +.SH DIAGNOSTICS +.LP +rstat: RPC: Program not registered +.IP +The +.B rstat_svc +daemon has not been started on the remote host. +.LP +rstat: RPC: Timed out +.IP +A communication error occurred. Either the network is +excessively congested, or the +.B rstat_svc +daemon has terminated on the remote host. +.LP +rstat: RPC: Port mapper failure - RPC: Timed out +.IP +The remote host is not running the portmapper (see +.BR portmap(8) ), +and cannot accommodate any RPC-based services. The host may be down. +.SH "SEE ALSO" +.BR portmap (8), +.BR rstat_svc (8) diff --git a/c/src/exec/librpc/src/rpc/rstat_svc.8 b/c/src/exec/librpc/src/rpc/rstat_svc.8 index e69de29bb2..e2eae8be3d 100644 --- a/c/src/exec/librpc/src/rpc/rstat_svc.8 +++ b/c/src/exec/librpc/src/rpc/rstat_svc.8 @@ -0,0 +1,22 @@ +.\" $FreeBSD: src/lib/libc/rpc/rstat_svc.8,v 1.5 1999/08/28 00:00:47 peter Exp $ +.\" @(#)rstat_svc.8c 2.2 88/08/03 4.0 RPCSRC; from 1.10 87/09/09 SMI +.TH RSTAT_SVC 8 "24 November 1987" +.SH NAME +rstat_svc \- kernel statistics server +.SH SYNOPSIS +.B /etc/rstat_svc +.SH DESCRIPTION +.LP +.B rstat_svc +is a server which returns performance statistics +obtained from the kernel. +These statistics are graphically displayed by the Sun Microsystems program, +.BR perfmeter (1). +The +.B rstat_svc +daemon is normally invoked at boot time through /etc/rc.local. +.PP +.B rstat_svc +uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x. +.\" .SH "SEE ALSO" +.\" .BR rstat (1), diff --git a/c/src/exec/librpc/src/rpc/rtems_portmapper.c b/c/src/exec/librpc/src/rpc/rtems_portmapper.c index e69de29bb2..e33a3103c9 100644 --- a/c/src/exec/librpc/src/rpc/rtems_portmapper.c +++ b/c/src/exec/librpc/src/rpc/rtems_portmapper.c @@ -0,0 +1,488 @@ +/* + * 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 + +static void reg_service(); +static void callit(); +static struct pmaplist *pmaplist; +static int debugging = 0; + +#include +#define fork() (-1) + + +static rtems_task rtems_portmapper (rtems_task_argument unused) +{ + SVCXPRT *xprt; + int sock; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + register struct pmaplist *pml; + + rtems_rpc_task_init (); + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("portmap cannot create socket"); + rtems_task_delete (RTEMS_SELF); + } + + addr.sin_addr.s_addr = 0; + addr.sin_family = AF_INET; + addr.sin_port = htons(PMAPPORT); + if (bind(sock, (struct sockaddr *)&addr, len) != 0) { + perror("portmap cannot bind"); + close (sock); + rtems_task_delete (RTEMS_SELF); + } + + if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { + fprintf(stderr, "couldn't do udp_create\n"); + close (sock); + rtems_task_delete (RTEMS_SELF); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); + pml->pml_next = 0; + pml->pml_map.pm_prog = PMAPPROG; + pml->pml_map.pm_vers = PMAPVERS; + pml->pml_map.pm_prot = IPPROTO_UDP; + pml->pml_map.pm_port = PMAPPORT; + pmaplist = pml; + + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + perror("portmap cannot create socket"); + close (sock); + rtems_task_delete (RTEMS_SELF); + } + if (bind(sock, (struct sockaddr *)&addr, len) != 0) { + perror("portmap cannot bind"); + close (sock); + rtems_task_delete (RTEMS_SELF); + } + if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) + == (SVCXPRT *)NULL) { + fprintf(stderr, "couldn't do tcp_create\n"); + close (sock); + rtems_task_delete (RTEMS_SELF); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); + pml->pml_map.pm_prog = PMAPPROG; + pml->pml_map.pm_vers = PMAPVERS; + pml->pml_map.pm_prot = IPPROTO_TCP; + pml->pml_map.pm_port = PMAPPORT; + pml->pml_next = pmaplist; + pmaplist = pml; + + (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); + + svc_run(); + fprintf(stderr, "run_svc returned unexpectedly\n"); + close (sock); + rtems_task_delete (RTEMS_SELF); +} + +static struct pmaplist * +find_service(prog, vers, prot) +u_long prog; +u_long vers; +{ +register struct pmaplist *hit = NULL; +register struct pmaplist *pml; + +for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { + if ((pml->pml_map.pm_prog != prog) || + (pml->pml_map.pm_prot != prot)) + continue; + hit = pml; + if (pml->pml_map.pm_vers == vers) + break; +} + return (hit); +} + +/* + * 1 OK, 0 not + */ +static void reg_service(rqstp, xprt) + struct svc_req *rqstp; + SVCXPRT *xprt; +{ + struct pmap reg; + struct pmaplist *pml, *prevpml, *fnd; + int ans, port; + caddr_t t; + +#ifdef DEBUG + fprintf(stderr, "server: about do a switch\n"); +#endif + switch (rqstp->rq_proc) { + + case PMAPPROC_NULL: + /* + * Null proc call + */ + if ((!svc_sendreply(xprt, xdr_void, NULL)) && 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 { + /* + * 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; + 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 */ + 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 { + 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 { + if ((!svc_sendreply(xprt, xdr_pmaplist, + (caddr_t)&pmaplist)) && 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: + svcerr_noproc(xprt); + break; + } +} + + +/* + * Stuff for the rmtcall service + */ +#define ARGSIZE 9000 + +struct encap_parms { + u_long arglen; + char *args; +}; + +static bool_t +xdr_encap_parms(xdrs, epp) + XDR *xdrs; + struct encap_parms *epp; +{ + + return (xdr_bytes(xdrs, &(epp->args), (u_int*)&(epp->arglen), ARGSIZE)); +} + +struct rmtcallargs { + u_long rmt_prog; + u_long rmt_vers; + u_long rmt_port; + u_long rmt_proc; + struct encap_parms rmt_args; +}; + +static bool_t +xdr_rmtcall_args(xdrs, cap) + register XDR *xdrs; + register struct rmtcallargs *cap; +{ + + /* does not get a port number */ + if (xdr_u_long(xdrs, &(cap->rmt_prog)) && + xdr_u_long(xdrs, &(cap->rmt_vers)) && + xdr_u_long(xdrs, &(cap->rmt_proc))) { + return (xdr_encap_parms(xdrs, &(cap->rmt_args))); + } + return (FALSE); +} + +static bool_t +xdr_rmtcall_result(xdrs, cap) + register XDR *xdrs; + register struct rmtcallargs *cap; +{ + if (xdr_u_long(xdrs, &(cap->rmt_port))) + return (xdr_encap_parms(xdrs, &(cap->rmt_args))); + return (FALSE); +} + +/* + * only worries about the struct encap_parms part of struct rmtcallargs. + * The arglen must already be set!! + */ +static bool_t +xdr_opaque_parms(xdrs, cap) + XDR *xdrs; + struct rmtcallargs *cap; +{ + + return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); +} + +/* + * This routine finds and sets the length of incoming opaque paraters + * and then calls xdr_opaque_parms. + */ +static bool_t +xdr_len_opaque_parms(xdrs, cap) + register XDR *xdrs; + struct rmtcallargs *cap; +{ + register u_int beginpos, lowpos, highpos, currpos, pos; + + beginpos = lowpos = pos = xdr_getpos(xdrs); + highpos = lowpos + ARGSIZE; + while ((int)(highpos - lowpos) >= 0) { + currpos = (lowpos + highpos) / 2; + if (xdr_setpos(xdrs, currpos)) { + pos = currpos; + lowpos = currpos + 1; + } else { + highpos = currpos - 1; + } + } + xdr_setpos(xdrs, beginpos); + cap->rmt_args.arglen = pos - beginpos; + return (xdr_opaque_parms(xdrs, cap)); +} + +/* + * Call a remote procedure service + * This procedure is very quiet when things go wrong. + * The proc is written to support broadcast rpc. In the broadcast case, + * a machine should shut-up instead of complain, less the requestor be + * overrun with complaints at the expense of not hearing a valid reply ... + * + * This now forks so that the program & process that it calls can call + * back to the portmapper. + */ +static void +callit(rqstp, xprt) + struct svc_req *rqstp; + SVCXPRT *xprt; +{ + struct rmtcallargs a; + struct pmaplist *pml; + u_short port; + struct sockaddr_in me; + int pid, socket = -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; + if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL) + return; + /* + * fork a child to do the work. Parent immediately returns. + * Child exits upon completion. + */ + if ((pid = fork()) != 0) { + if (debugging && (pid < 0)) { + fprintf(stderr, "portmap CALLIT: cannot fork.\n"); + } + 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, &socket); + if (client != (CLIENT *)NULL) { + if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) { + client->cl_auth = authunix_create(au->aup_machname, + au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); + } + a.rmt_port = (u_long)port; + if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, + xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) { + svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); + } + AUTH_DESTROY(client->cl_auth); + clnt_destroy(client); + } + (void)close(socket); + exit(0); +} + +/* + * Start the RPC portmapper + */ +int rtems_rpc_start_portmapper (int priority) +{ + rtems_mode mode; + rtems_status_code sc; + rtems_id tid; + static int started; + + rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &mode); + if (started) { + rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode); + return RTEMS_SUCCESSFUL; + } + sc = rtems_task_create (rtems_build_name('P', 'M', 'A', 'P'), + priority, + 8000, + RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), + RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, + &tid); + if (sc != RTEMS_SUCCESSFUL) { + rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode); + return sc; + } + sc = rtems_task_start (tid, rtems_portmapper, 0); + if (sc != RTEMS_SUCCESSFUL) { + rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode); + return sc; + } + started = 1; + rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode); + return RTEMS_SUCCESSFUL; +} diff --git a/c/src/exec/librpc/src/rpc/rtems_rpc.c b/c/src/exec/librpc/src/rpc/rtems_rpc.c index e69de29bb2..d2666e2f91 100644 --- a/c/src/exec/librpc/src/rpc/rtems_rpc.c +++ b/c/src/exec/librpc/src/rpc/rtems_rpc.c @@ -0,0 +1,56 @@ +/* + * RTEMS multi-tasking support + */ + +#include +#include +#include + +/* + * RPC variables for single-thread + */ +static struct rtems_rpc_task_variables rpc_default = { + -1, /* svc_maxfd */ +}; + +/* + * RPC values for initializing a new per-task set of variables + */ +static const struct rtems_rpc_task_variables rpc_init = { + -1, /* svc_maxfd */ +}; + +/* + * Per-task pointer to RPC data + */ +void *rtems_rpc_task_variables = &rpc_default; + +/* + * Set up per-task RPC variables + */ +int rtems_rpc_task_init (void) +{ + rtems_status_code sc; + struct rtems_rpc_task_variables *tvp; + + if (rtems_rpc_task_variables == &rpc_default) { + tvp = malloc (sizeof *tvp); + if (tvp == NULL) + return RTEMS_NO_MEMORY; + /* + * FIXME: Should have destructor which cleans up + * all RPC stuff: + * - Close all files + * - Go through and free linked list elements + * - Free other allocated memory (e.g. clnt_perror_buf) + */ + sc = rtems_task_variable_add (RTEMS_SELF, &rtems_rpc_task_variables, NULL); + if (sc != RTEMS_SUCCESSFUL) { + free (tvp); + return sc; + } + *tvp = rpc_init; + rtems_rpc_task_variables = tvp; + } + return RTEMS_SUCCESSFUL; +} diff --git a/c/src/exec/librpc/src/rpc/rtime.3 b/c/src/exec/librpc/src/rpc/rtime.3 index e69de29bb2..ad3e538c43 100644 --- a/c/src/exec/librpc/src/rpc/rtime.3 +++ b/c/src/exec/librpc/src/rpc/rtime.3 @@ -0,0 +1,47 @@ +.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI +.\" $FreeBSD: src/lib/libc/rpc/rtime.3,v 1.4 2000/03/02 09:13:48 sheldonh Exp $ +.\" +.TH RTIME 3 "22 November 1987" +.SH NAME +rtime \- get remote time +.SH SYNOPSIS +.nf +.B #include +.B #include +.B #include +.LP +.B int rtime(addrp, timep, timeout) +.B struct sockaddr_in \(**addrp; +.B struct timeval \(**timep; +.B struct timeval \(**timeout; +.fi +.SH DESCRIPTION +.B rtime(\|) +consults the Internet Time Server at the address pointed to by +.I addrp +and returns the remote time in the +.B timeval +struct pointed to by +.IR timep . +Normally, the +.SM UDP +protocol is used when consulting the Time Server. +The +.I timeout +parameter specifies how long the +routine should wait before giving +up when waiting for a reply. If +.I timeout +is specified as +.SM NULL\s0, +however, the routine will instead use +.SM TCP +and block until a reply is received from the time server. +.LP +The routine returns 0 if it is successful. +Otherwise, +it returns \-1 and +.B errno +is set to reflect the cause of the error. +.SH "SEE ALSO" +.BR timed (8c) diff --git a/c/src/exec/librpc/src/rpc/rtime.c b/c/src/exec/librpc/src/rpc/rtime.c index e69de29bb2..b37d6bdb52 100644 --- a/c/src/exec/librpc/src/rpc/rtime.c +++ b/c/src/exec/librpc/src/rpc/rtime.c @@ -0,0 +1,157 @@ +/* + * 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. + + */ + +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket. Since timeserver returns + * with time of day in seconds since Jan 1, 1900, must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; */ +static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/rtime.c,v 1.5 2000/01/27 23:06:41 jasone Exp $"; +#endif + +extern int _rpc_dtablesize __P(( void )); + +#define NYEARS (unsigned long)(1970 - 1900) +#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4))) + +static void do_close __P(( int )); + +int +rtime(addrp, timep, timeout) + struct sockaddr_in *addrp; + struct timeval *timep; + struct timeval *timeout; +{ + int s; + fd_set readfds; + int res; + unsigned long thetime; + struct sockaddr_in from; + int fromlen; + int type; + struct servent *serv; + + if (timeout == NULL) { + type = SOCK_STREAM; + } else { + type = SOCK_DGRAM; + } + s = socket(AF_INET, type, 0); + if (s < 0) { + return(-1); + } + addrp->sin_family = AF_INET; + + /* TCP and UDP port are the same in this case */ + if ((serv = getservbyname("time", "tcp")) == NULL) { + return(-1); + } + + addrp->sin_port = serv->s_port; + + if (type == SOCK_DGRAM) { + res = sendto(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)addrp, sizeof(*addrp)); + if (res < 0) { + do_close(s); + return(-1); + } + do { + FD_ZERO(&readfds); + FD_SET(s, &readfds); + res = select(_rpc_dtablesize(), &readfds, + (fd_set *)NULL, (fd_set *)NULL, timeout); + } while (res < 0 && errno == EINTR); + if (res <= 0) { + if (res == 0) { + errno = ETIMEDOUT; + } + do_close(s); + return(-1); + } + fromlen = sizeof(from); + res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)&from, &fromlen); + do_close(s); + if (res < 0) { + return(-1); + } + } else { + if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { + do_close(s); + return(-1); + } + res = _read(s, (char *)&thetime, sizeof(thetime)); + do_close(s); + if (res < 0) { + return(-1); + } + } + if (res != sizeof(thetime)) { + errno = EIO; + return(-1); + } + thetime = ntohl(thetime); + timep->tv_sec = thetime - TOFFSET; + timep->tv_usec = 0; + return(0); +} + +static void +do_close(s) + int s; +{ + int save; + + save = errno; + (void)_close(s); + errno = save; +} diff --git a/c/src/exec/librpc/src/rpc/svc.c b/c/src/exec/librpc/src/rpc/svc.c index e69de29bb2..92832a589b 100644 --- a/c/src/exec/librpc/src/rpc/svc.c +++ b/c/src/exec/librpc/src/rpc/svc.c @@ -0,0 +1,491 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc.c,v 1.14 1999/08/28 00:00:48 peter Exp $"; +#endif + +/* + * svc.c, Server-side remote procedure call interface. + * + * There are two sets of procedures here. The xprt routines are + * for handling transport handles. The svc routines handle the + * list of service routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include + +#define xports ((SVCXPRT **)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_xports) +#define xportssize (((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_xportssize) + +#define NULL_SVC ((struct svc_callout *)0) +#define RQCRED_SIZE 400 /* this size is excessive */ + +#define max(a, b) (a > b ? a : b) + +/* + * The services list + * Each entry represents a set of procedures (an rpc program). + * The dispatch routine takes request structs and runs the + * apropriate procedure. + */ +struct svc_callout { + struct svc_callout *sc_next; + u_long sc_prog; + u_long sc_vers; + void (*sc_dispatch)(); +}; +#define svc_head (struct svc_callout *)(((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_svc_head) + +static struct svc_callout *svc_find(); + +/* *************** SVCXPRT related stuff **************** */ + +/* + * Activate a transport handle. + */ +void +xprt_register(xprt) + SVCXPRT *xprt; +{ + register int sock = xprt->xp_sock; + + if (sock + 1 > __svc_fdsetsize) { + int bytes = sizeof (fd_set); + fd_set *fds; + + fds = (fd_set *)malloc(bytes); + memset(fds, 0, bytes); + if (__svc_fdset) { + memcpy(fds, __svc_fdset, bytes); + free(__svc_fdset); + } + __svc_fdset = fds; + __svc_fdsetsize = bytes * NBBY; + } + + if (sock < FD_SETSIZE) + 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; + } + xports[sock] = xprt; + svc_maxfd = max(svc_maxfd, sock); +} + +/* + * De-activate a transport handle. + */ +void +xprt_unregister(xprt) + SVCXPRT *xprt; +{ + register int sock = xprt->xp_sock; + + if (xports[sock] == xprt) { + xports[sock] = (SVCXPRT *)0; + if (sock < FD_SETSIZE) + FD_CLR(sock, &svc_fdset); + FD_CLR(sock, __svc_fdset); + if (sock == svc_maxfd) { + for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--) + if (xports[svc_maxfd]) + break; + } + /* + * XXX could use svc_maxfd as a hint to + * decrease the size of __svc_fdset + */ + } +} + + +/* ********************** CALLOUT list related stuff ************* */ + +/* + * 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(xprt, prog, vers, dispatch, protocol) + SVCXPRT *xprt; + u_long prog; + u_long vers; + void (*dispatch)(); + int protocol; +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) { + 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) { + return (FALSE); + } + s->sc_prog = prog; + s->sc_vers = vers; + s->sc_dispatch = dispatch; + s->sc_next = svc_head; + svc_head = s; +pmap_it: + /* now register the information with the local binder service */ + if (protocol) { + return (pmap_set(prog, vers, protocol, xprt->xp_port)); + } + return (TRUE); +} + +/* + * Remove a service program from the callout list. + */ +void +svc_unregister(prog, vers) + u_long prog; + u_long vers; +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find(prog, vers, &prev)) == NULL_SVC) + return; + if (prev == NULL_SVC) { + 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)); + /* now unregister the information with the local binder service */ + (void)pmap_unset(prog, vers); +} + +/* + * Search the callout list for a program number, return the callout + * struct. + */ +static struct svc_callout * +svc_find(prog, vers, prev) + u_long prog; + u_long vers; + struct svc_callout **prev; +{ + register 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; + p = s; + } +done: + *prev = p; + return (s); +} + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* + * Send a reply to an rpc request + */ +bool_t +svc_sendreply(xprt, xdr_results, xdr_location) + register SVCXPRT *xprt; + xdrproc_t xdr_results; + caddr_t xdr_location; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SUCCESS; + rply.acpted_rply.ar_results.where = xdr_location; + rply.acpted_rply.ar_results.proc = xdr_results; + return (SVC_REPLY(xprt, &rply)); +} + +/* + * No procedure error reply + */ +void +svcerr_noproc(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROC_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Can't decode args error reply + */ +void +svcerr_decode(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = GARBAGE_ARGS; + SVC_REPLY(xprt, &rply); +} + +/* + * Some system error + */ +void +svcerr_systemerr(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SYSTEM_ERR; + SVC_REPLY(xprt, &rply); +} + +/* + * Authentication error reply + */ +void +svcerr_auth(xprt, why) + SVCXPRT *xprt; + enum auth_stat why; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_DENIED; + rply.rjcted_rply.rj_stat = AUTH_ERROR; + rply.rjcted_rply.rj_why = why; + SVC_REPLY(xprt, &rply); +} + +/* + * Auth too weak error reply + */ +void +svcerr_weakauth(xprt) + SVCXPRT *xprt; +{ + + svcerr_auth(xprt, AUTH_TOOWEAK); +} + +/* + * Program unavailable error reply + */ +void +svcerr_noprog(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Program version mismatch error reply + */ +void +svcerr_progvers(xprt, low_vers, high_vers) + register SVCXPRT *xprt; + u_long low_vers; + u_long high_vers; +{ + struct rpc_msg rply; + + 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; + SVC_REPLY(xprt, &rply); +} + +/* ******************* SERVER INPUT STUFF ******************* */ + +/* + * Get server side input from some transport. + * + * Statement of authentication parameters management: + * This function owns and manages all authentication parameters, specifically + * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and + * the "cooked" credentials (rqst->rq_clntcred). + * However, this function does not know the structure of the cooked + * credentials, so it make the following assumptions: + * a) the structure is contiguous (no pointers), and + * b) the cred structure size does not exceed RQCRED_SIZE bytes. + * In all events, all three parameters are freed upon exit from this routine. + * The storage is trivially management on the call stack in user land, but + * is mallocated in kernel land. + */ + +void +svc_getreq(rdfds) + int rdfds; +{ + fd_set readfds; + + FD_ZERO(&readfds); + readfds.fds_bits[0] = rdfds; + svc_getreqset(&readfds); +} + +void +svc_getreqset(readfds) + fd_set *readfds; +{ + svc_getreqset2(readfds, FD_SETSIZE); +} + +void +svc_getreqset2(readfds, width) + fd_set *readfds; + int width; +{ + enum xprt_stat stat; + struct rpc_msg msg; + int prog_found; + u_long low_vers; + u_long high_vers; + struct svc_req r; + register SVCXPRT *xprt; + register int bit; + register int sock; + register fd_mask mask, *maskp; + char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); + + + maskp = readfds->fds_bits; + for (sock = 0; sock < width; sock += NFDBITS) { + for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) { + /* sock has input waiting */ + xprt = xports[sock + bit - 1]; + if (xprt == NULL) + /* But do we control sock? */ + continue; + /* now receive msgs from xprtprt (support batch calls) */ + do { + if (SVC_RECV(xprt, &msg)) { + + /* now find the exported program and call it */ + register struct svc_callout *s; + enum auth_stat why; + + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + /* first authenticate the message */ + if ((why= _authenticate(&r, &msg)) != AUTH_OK) { + svcerr_auth(xprt, why); + goto call_done; + } + /* now match message with a registered service*/ + prog_found = FALSE; + low_vers = (u_long) - 1; + high_vers = 0; + for (s = svc_head; s != NULL_SVC; s = s->sc_next) { + if (s->sc_prog == r.rq_prog) { + if (s->sc_vers == r.rq_vers) { + (*s->sc_dispatch)(&r, xprt); + goto call_done; + } /* found correct version */ + prog_found = TRUE; + if (s->sc_vers < low_vers) + low_vers = s->sc_vers; + if (s->sc_vers > high_vers) + high_vers = s->sc_vers; + } /* found correct program */ + } + /* + * if we got here, the program or version + * is not served ... + */ + if (prog_found) + svcerr_progvers(xprt, + low_vers, high_vers); + else + svcerr_noprog(xprt); + /* Fall through to ... */ + } + call_done: + if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ + SVC_DESTROY(xprt); + break; + } + } while (stat == XPRT_MOREREQS); + } + } +} diff --git a/c/src/exec/librpc/src/rpc/svc_auth.c b/c/src/exec/librpc/src/rpc/svc_auth.c index e69de29bb2..f95f101f33 100644 --- a/c/src/exec/librpc/src/rpc/svc_auth.c +++ b/c/src/exec/librpc/src/rpc/svc_auth.c @@ -0,0 +1,216 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ + +#ident "@(#)svc_auth.c 1.16 94/04/24 SMI" + +#if !defined(lint) && defined(SCCSIDS) +#if 0 +static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro"; +#else +static const char rcsid[] = + "$FreeBSD: src/lib/libc/rpc/svc_auth.c,v 1.7 1999/12/29 05:04:16 peter Exp $"; +#endif +#endif + +/* + * svc_auth.c, Server-side rpc authenticator interface. + * + */ + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#endif +#include + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +enum auth_stat _svcauth_null(); /* no authentication */ +enum auth_stat _svcauth_unix(); /* (system) unix style (uid, gids) */ +enum auth_stat _svcauth_short(); /* short hand unix style */ +enum auth_stat _svcauth_des(); /* des style */ + +/* declarations to allow servers to specify new authentication flavors */ +struct authsvc { + int flavor; + enum auth_stat (*handler)(); + struct authsvc *next; +}; +#define Auths ((struct authsvc *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_auths_Auths) + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-alloctaed; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate(rqst, msg) + register struct svc_req *rqst; + struct rpc_msg *msg; +{ + register int cred_flavor; + register struct authsvc *asp; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + 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)); + 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. + */ +#ifdef DES_BUILTIN + case AUTH_DES: + return(_svcauth_des(rqst, msg)); +#endif + } + + /* flavor doesn't match any of the builtin types, so try new ones */ + for (asp = Auths; asp; asp = asp->next) { + if (asp->flavor == cred_flavor) { + enum auth_stat as; + + as = (*asp->handler)(rqst, msg); + return (as); + } + } + + return (AUTH_REJECTEDCRED); +} + +/*ARGSUSED*/ +enum auth_stat +_svcauth_null(rqst, msg) + struct svc_req *rqst; + struct rpc_msg *msg; +{ + return (AUTH_OK); +} + +/* + * Allow the rpc service to register new authentication types that it is + * prepared to handle. When an authentication flavor is registered, + * the flavor is checked against already registered values. If not + * registered, then a new Auths entry is added on the list. + * + * There is no provision to delete a registration once registered. + * + * This routine returns: + * 0 if registration successful + * 1 if flavor already registered + * -1 if can't register (errno set) + */ + +int +svc_auth_reg(cred_flavor, handler) + register int cred_flavor; + enum auth_stat (*handler)(); +{ + register struct authsvc *asp; + + switch (cred_flavor) { + case AUTH_NULL: + case AUTH_UNIX: + case AUTH_SHORT: +#ifdef DES_BUILTIN + case AUTH_DES: +#endif + /* already registered */ + return (1); + + default: + for (asp = Auths; asp; asp = asp->next) { + if (asp->flavor == cred_flavor) { + /* already registered */ + return (1); + } + } + + /* this is a new one, so go ahead and register it */ + asp = (struct authsvc *)mem_alloc(sizeof (*asp)); + if (asp == NULL) { + return (-1); + } + asp->flavor = cred_flavor; + asp->handler = handler; + asp->next = Auths; + Auths = asp; + break; + } + return (0); +} diff --git a/c/src/exec/librpc/src/rpc/svc_auth_des.c b/c/src/exec/librpc/src/rpc/svc_auth_des.c index e69de29bb2..a107168e30 100644 --- a/c/src/exec/librpc/src/rpc/svc_auth_des.c +++ b/c/src/exec/librpc/src/rpc/svc_auth_des.c @@ -0,0 +1,531 @@ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * 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 + */ + +/* + * svcauth_des.c, server-side des authentication + * + * We insure for the service the following: + * (1) The timestamp microseconds do not exceed 1 million. + * (2) The timestamp plus the window is less than the current time. + * (3) The timestamp is not less than the one previously + * seen in the current session. + * + * It is up to the server to determine if the window size is + * too small . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; */ +static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/svc_auth_des.c,v 1.3 1999/08/28 00:00:48 peter Exp $"; +#endif + +#define debug(msg) printf("svcauth_des: %s\n", msg) + +#define USEC_PER_SEC ((u_long) 1000000L) +#define BEFORE(t1, t2) timercmp(t1, t2, <) + +/* + * LRU cache of conversation keys and some other useful items. + */ +#define AUTHDES_CACHESZ 64 +struct cache_entry { + des_block key; /* conversation key */ + char *rname; /* client's name */ + u_int window; /* credential lifetime window */ + struct timeval laststamp; /* detect replays of creds */ + char *localcred; /* generic local credential */ +}; +static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */; +static short *authdes_lru/* [AUTHDES_CACHESZ] */; + +static void cache_init(); /* initialize the cache */ +static short cache_spot(); /* find an entry in the cache */ +static void cache_ref(/*short sid*/); /* note that sid was ref'd */ + +static void invalidate(); /* invalidate entry in cache */ + +/* + * cache statistics + */ +static struct { + u_long ncachehits; /* times cache hit, and is not replay */ + u_long ncachereplays; /* times cache hit, and is replay */ + u_long ncachemisses; /* times cache missed */ +} svcauthdes_stats; + +/* + * Service side authenticator for AUTH_DES + */ +enum auth_stat +_svcauth_des(rqst, msg) + register struct svc_req *rqst; + register struct rpc_msg *msg; +{ + + register long *ixdr; + des_block cryptbuf[2]; + register struct authdes_cred *cred; + struct authdes_verf verf; + int status; + register struct cache_entry *entry; + short sid = 0; + des_block *sessionkey; + des_block ivec; + u_int window; + struct timeval timestamp; + u_long namelen; + struct area { + struct authdes_cred area_cred; + char area_netname[MAXNETNAMELEN+1]; + } *area; + + if (authdes_cache == NULL) { + cache_init(); + } + + area = (struct area *)rqst->rq_clntcred; + cred = (struct authdes_cred *)&area->area_cred; + + /* + * Get the credential + */ + ixdr = (long *)msg->rm_call.cb_cred.oa_base; + cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + namelen = IXDR_GET_U_LONG(ixdr); + if (namelen > MAXNETNAMELEN) { + return (AUTH_BADCRED); + } + cred->adc_fullname.name = area->area_netname; + bcopy((char *)ixdr, cred->adc_fullname.name, + (u_int)namelen); + cred->adc_fullname.name[namelen] = 0; + ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); + cred->adc_fullname.key.key.high = (u_long)*ixdr++; + cred->adc_fullname.key.key.low = (u_long)*ixdr++; + cred->adc_fullname.window = (u_long)*ixdr++; + break; + case ADN_NICKNAME: + cred->adc_nickname = (u_long)*ixdr++; + break; + default: + return (AUTH_BADCRED); + } + + /* + * Get the verifier + */ + ixdr = (long *)msg->rm_call.cb_verf.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++; + + + /* + * Get the conversation key + */ + if (cred->adc_namekind == ADN_FULLNAME) { + netobj pkey; + char pkey_data[1024]; + + sessionkey = &cred->adc_fullname.key; + if (! getpublickey(cred->adc_fullname.name, pkey_data)) { + debug("getpublickey"); + return(AUTH_BADCRED); + } + pkey.n_bytes = pkey_data; + pkey.n_len = strlen(pkey_data) + 1; + if (key_decryptsession_pk(cred->adc_fullname.name, &pkey, + sessionkey) < 0) { + debug("decryptsessionkey"); + return (AUTH_BADCRED); /* key not found */ + } + } else { /* ADN_NICKNAME */ + sid = (short)cred->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { + debug("bad nickname"); + return (AUTH_BADCRED); /* garbled credential */ + } + sessionkey = &authdes_cache[sid].key; + } + + + /* + * Decrypt the timestamp + */ + cryptbuf[0] = verf.adv_xtimestamp; + if (cred->adc_namekind == ADN_FULLNAME) { + cryptbuf[1].key.high = cred->adc_fullname.window; + cryptbuf[1].key.low = verf.adv_winverf; + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt((char *)sessionkey, (char *)cryptbuf, + 2*sizeof(des_block), DES_DECRYPT | DES_HW, + (char *)&ivec); + } else { + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_DECRYPT | DES_HW); + } + if (DES_FAILED(status)) { + debug("decryption failure"); + return (AUTH_FAILED); /* system error */ + } + + /* + * XDR the decrypted timestamp + */ + ixdr = (long *)cryptbuf; + timestamp.tv_sec = IXDR_GET_LONG(ixdr); + timestamp.tv_usec = IXDR_GET_LONG(ixdr); + + /* + * Check for valid credentials and verifiers. + * They could be invalid because the key was flushed + * out of the cache, and so a new session should begin. + * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. + */ + { + struct timeval current; + int nick; + int winverf; + + if (cred->adc_namekind == ADN_FULLNAME) { + window = IXDR_GET_U_LONG(ixdr); + winverf = IXDR_GET_U_LONG(ixdr); + if (winverf != window - 1) { + debug("window verifier mismatch"); + return (AUTH_BADCRED); /* garbled credential */ + } + sid = cache_spot(sessionkey, cred->adc_fullname.name, + ×tamp); + if (sid < 0) { + debug("replayed credential"); + return (AUTH_REJECTEDCRED); /* replay */ + } + nick = 0; + } else { /* ADN_NICKNAME */ + window = authdes_cache[sid].window; + nick = 1; + } + + if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) { + debug("invalid usecs"); + /* cached out (bad key), or garbled verifier */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); + } + if (nick && BEFORE(×tamp, + &authdes_cache[sid].laststamp)) { + debug("timestamp before last seen"); + return (AUTH_REJECTEDVERF); /* replay */ + } + (void) gettimeofday(¤t, (struct timezone *)NULL); + current.tv_sec -= window; /* allow for expiration */ + if (!BEFORE(¤t, ×tamp)) { + debug("timestamp expired"); + /* replay, or garbled credential */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); + } + } + + /* + * Set up the reply verifier + */ + verf.adv_nickname = (u_long)sid; + + /* + * xdr the timestamp before encrypting + */ + ixdr = (long *)cryptbuf; + IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); + IXDR_PUT_LONG(ixdr, timestamp.tv_usec); + + /* + * encrypt the timestamp + */ + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + if (DES_FAILED(status)) { + debug("encryption failure"); + return (AUTH_FAILED); /* system error */ + } + verf.adv_xtimestamp = cryptbuf[0]; + + /* + * Serialize the reply verifier, and update rqst + */ + ixdr = (long *)msg->rm_call.cb_verf.oa_base; + *ixdr++ = (long)verf.adv_xtimestamp.key.high; + *ixdr++ = (long)verf.adv_xtimestamp.key.low; + *ixdr++ = (long)verf.adv_int_u; + + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES; + rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + (char *)ixdr - msg->rm_call.cb_verf.oa_base; + + /* + * We succeeded, commit the data to the cache now and + * finish cooking the credential. + */ + entry = &authdes_cache[sid]; + entry->laststamp = timestamp; + cache_ref(sid); + if (cred->adc_namekind == ADN_FULLNAME) { + cred->adc_fullname.window = window; + cred->adc_nickname = (u_long)sid; /* save nickname */ + if (entry->rname != NULL) { + mem_free(entry->rname, strlen(entry->rname) + 1); + } + entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name) + + 1); + if (entry->rname != NULL) { + (void) strcpy(entry->rname, cred->adc_fullname.name); + } else { + debug("out of memory"); + } + entry->key = *sessionkey; + entry->window = window; + invalidate(entry->localcred); /* mark any cached cred invalid */ + } else { /* ADN_NICKNAME */ + /* + * nicknames are cooked into fullnames + */ + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = entry->rname; + cred->adc_fullname.key = entry->key; + cred->adc_fullname.window = entry->window; + } + return (AUTH_OK); /* we made it!*/ +} + + +/* + * Initialize the cache + */ +static void +cache_init() +{ + register int i; + + authdes_cache = (struct cache_entry *) + mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ); + bzero((char *)authdes_cache, + sizeof(struct cache_entry) * AUTHDES_CACHESZ); + + authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ); + /* + * Initialize the lru list + */ + for (i = 0; i < AUTHDES_CACHESZ; i++) { + authdes_lru[i] = i; + } +} + + +/* + * Find the lru victim + */ +static short +cache_victim() +{ + return (authdes_lru[AUTHDES_CACHESZ-1]); +} + +/* + * Note that sid was referenced + */ +static void +cache_ref(sid) + register short sid; +{ + register int i; + register short curr; + register short prev; + + prev = authdes_lru[0]; + authdes_lru[0] = sid; + for (i = 1; prev != sid; i++) { + curr = authdes_lru[i]; + authdes_lru[i] = prev; + prev = curr; + } +} + + +/* + * Find a spot in the cache for a credential containing + * the items given. Return -1 if a replay is detected, otherwise + * return the spot in the cache. + */ +static short +cache_spot(key, name, timestamp) + register des_block *key; + char *name; + struct timeval *timestamp; +{ + register struct cache_entry *cp; + register int i; + register u_long hi; + + hi = key->key.high; + for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) { + if (cp->key.key.high == hi && + cp->key.key.low == key->key.low && + cp->rname != NULL && + bcmp(cp->rname, name, strlen(name) + 1) == 0) { + if (BEFORE(timestamp, &cp->laststamp)) { + svcauthdes_stats.ncachereplays++; + return (-1); /* replay */ + } + svcauthdes_stats.ncachehits++; + return (i); /* refresh */ + } + } + svcauthdes_stats.ncachemisses++; + return (cache_victim()); /* new credential */ +} + + +#if (defined(sun) || defined(vax) || defined(__FreeBSD__)) +/* + * Local credential handling stuff. + * NOTE: bsd unix dependent. + * Other operating systems should put something else here. + */ +#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ +#define INVALID -1 /* grouplen, if cache entry is invalid */ + +struct bsdcred { + short uid; /* cached uid */ + short gid; /* cached gid */ + short grouplen; /* length of cached groups */ + short groups[NGROUPS]; /* cached groups */ +}; + +/* + * Map a des credential into a unix cred. + * We cache the credential here so the application does + * not have to make an rpc call every time to interpret + * the credential. + */ +int +authdes_getucred(adc, uid, gid, grouplen, groups) + struct authdes_cred *adc; + uid_t *uid; + gid_t *gid; + int *grouplen; + register gid_t *groups; +{ + unsigned sid; + register int i; + uid_t i_uid; + gid_t i_gid; + int i_grouplen; + struct bsdcred *cred; + + sid = adc->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { + debug("invalid nickname"); + return (0); + } + cred = (struct bsdcred *)authdes_cache[sid].localcred; + if (cred == NULL) { + cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); + authdes_cache[sid].localcred = (char *)cred; + cred->grouplen = INVALID; + } + if (cred->grouplen == INVALID) { + /* + * not in cache: lookup + */ + if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, + &i_grouplen, groups)) + { + debug("unknown netname"); + cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ + return (0); + } + debug("missed ucred cache"); + *uid = cred->uid = i_uid; + *gid = cred->gid = i_gid; + *grouplen = cred->grouplen = i_grouplen; + for (i = i_grouplen - 1; i >= 0; i--) { + cred->groups[i] = groups[i]; /* int to short */ + } + return (1); + } else if (cred->grouplen == UNKNOWN) { + /* + * Already lookup up, but no match found + */ + return (0); + } + + /* + * cached credentials + */ + *uid = cred->uid; + *gid = cred->gid; + *grouplen = cred->grouplen; + for (i = cred->grouplen - 1; i >= 0; i--) { + groups[i] = cred->groups[i]; /* short to int */ + } + return (1); +} + +static void +invalidate(cred) + char *cred; +{ + if (cred == NULL) { + return; + } + ((struct bsdcred *)cred)->grouplen = INVALID; +} +#endif + diff --git a/c/src/exec/librpc/src/rpc/svc_auth_unix.c b/c/src/exec/librpc/src/rpc/svc_auth_unix.c index e69de29bb2..8b4e257a2c 100644 --- a/c/src/exec/librpc/src/rpc/svc_auth_unix.c +++ b/c/src/exec/librpc/src/rpc/svc_auth_unix.c @@ -0,0 +1,148 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_auth_unix.c,v 1.8 1999/08/28 00:00:49 peter Exp $"; +#endif + +/* + * svc_auth_unix.c + * Handles UNIX flavor authentication parameters on the service side of rpc. + * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT. + * _svcauth_unix does full blown unix style uid,gid+gids auth, + * _svcauth_short uses a shorthand auth to index into a cache of longhand auths. + * Note: the shorthand has been gutted for efficiency. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +/* + * Unix longhand authenticator + */ +enum auth_stat +_svcauth_unix(rqst, msg) + register struct svc_req *rqst; + register struct rpc_msg *msg; +{ + register enum auth_stat stat; + XDR xdrs; + register struct authunix_parms *aup; + register int32_t *buf; + struct area { + struct authunix_parms area_aup; + char area_machname[MAX_MACHINE_NAME+1]; + int area_gids[NGRPS]; + } *area; + u_int auth_len; + int str_len, gid_len; + register int i; + + area = (struct area *) rqst->rq_clntcred; + aup = &area->area_aup; + aup->aup_machname = area->area_machname; + aup->aup_gids = area->area_gids; + auth_len = (u_int)msg->rm_call.cb_cred.oa_length; + 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); + if (str_len > MAX_MACHINE_NAME) { + stat = AUTH_BADCRED; + goto done; + } + memcpy(aup->aup_machname, (caddr_t)buf, (u_int)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); + 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); + } + /* + * five is the smallest unix credentials structure - + * timestamp, hostname len (0), uid, gid, and gids len (0). + */ + if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { + (void) printf("bad auth_len gid %d str %d auth %d\n", + gid_len, str_len, auth_len); + stat = AUTH_BADCRED; + goto done; + } + } else if (! xdr_authunix_parms(&xdrs, aup)) { + xdrs.x_op = XDR_FREE; + (void)xdr_authunix_parms(&xdrs, aup); + stat = AUTH_BADCRED; + goto done; + } + + /* get the verifier */ + if ((u_int)msg->rm_call.cb_verf.oa_length) { + rqst->rq_xprt->xp_verf.oa_flavor = + msg->rm_call.cb_verf.oa_flavor; + rqst->rq_xprt->xp_verf.oa_base = + msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + msg->rm_call.cb_verf.oa_length; + } else { + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; + rqst->rq_xprt->xp_verf.oa_length = 0; + } + stat = AUTH_OK; +done: + XDR_DESTROY(&xdrs); + return (stat); +} + + +/* + * Shorthand unix authenticator + * Looks up longhand in a cache. + */ +/*ARGSUSED*/ +enum auth_stat +_svcauth_short(rqst, msg) + struct svc_req *rqst; + struct rpc_msg *msg; +{ + return (AUTH_REJECTEDCRED); +} diff --git a/c/src/exec/librpc/src/rpc/svc_raw.c b/c/src/exec/librpc/src/rpc/svc_raw.c index e69de29bb2..686c61bdd4 100644 --- a/c/src/exec/librpc/src/rpc/svc_raw.c +++ b/c/src/exec/librpc/src/rpc/svc_raw.c @@ -0,0 +1,169 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_raw.c,v 1.7 1999/08/28 00:00:49 peter Exp $"; +#endif + +/* + * 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. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include + +/* + * This is the "network" that we will be moving data over + */ +struct svc_raw_private { + char _raw_buf[UDPMSGSIZE]; + SVCXPRT server; + XDR xdr_stream; + char verf_body[MAX_AUTH_BYTES]; +}; +#define svcraw_private ((struct svc_raw_private *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_raw_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 +}; + +SVCXPRT * +svcraw_create() +{ + register struct svc_raw_private *srp = svcraw_private; + + if (srp == 0) { + srp = (struct svc_raw_private *)calloc(1, sizeof (*srp)); + if (srp == 0) + return (0); + } + srp->server.xp_sock = 0; + srp->server.xp_port = 0; + srp->server.xp_ops = &server_ops; + srp->server.xp_verf.oa_base = srp->verf_body; + xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE); + return (&srp->server); +} + +static enum xprt_stat +svcraw_stat() +{ + + return (XPRT_IDLE); +} + +static bool_t +svcraw_recv(xprt, msg) + SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svc_raw_private *srp = svcraw_private; + register XDR *xdrs; + + if (srp == 0) + return (0); + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_DECODE; + XDR_SETPOS(xdrs, 0); + if (! xdr_callmsg(xdrs, msg)) + return (FALSE); + return (TRUE); +} + +static bool_t +svcraw_reply(xprt, msg) + SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svc_raw_private *srp = svcraw_private; + register XDR *xdrs; + + if (srp == 0) + return (FALSE); + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, 0); + if (! xdr_replymsg(xdrs, msg)) + return (FALSE); + (void)XDR_GETPOS(xdrs); /* called just for overhead */ + return (TRUE); +} + +static bool_t +svcraw_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register struct svc_raw_private *srp = svcraw_private; + + if (srp == 0) + return (FALSE); + return ((*xdr_args)(&srp->xdr_stream, args_ptr)); +} + +static bool_t +svcraw_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register struct svc_raw_private *srp = svcraw_private; + register XDR *xdrs; + + if (srp == 0) + return (FALSE); + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static void +svcraw_destroy() +{ +} diff --git a/c/src/exec/librpc/src/rpc/svc_run.c b/c/src/exec/librpc/src/rpc/svc_run.c index e69de29bb2..5e8a9e683a 100644 --- a/c/src/exec/librpc/src/rpc/svc_run.c +++ b/c/src/exec/librpc/src/rpc/svc_run.c @@ -0,0 +1,83 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_run.c,v 1.10 1999/08/28 00:00:49 peter Exp $"; +#endif + +/* + * This is the rpc server side idle loop + * Wait for input, call server program. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void +svc_run() +{ + fd_set *fds; + + for (;;) { + if (__svc_fdset) { + int bytes = sizeof (fd_set); + fds = (fd_set *)malloc(bytes); + memcpy(fds, __svc_fdset, bytes); + } else + fds = NULL; + switch (select(svc_maxfd + 1, fds, NULL, NULL, + (struct timeval *)0)) { + case -1: + if (errno == EINTR) { + if (fds) + free(fds); + continue; + } + perror("svc_run: - select failed"); + if (fds) + free(fds); + return; + case 0: + if (fds) + free(fds); + continue; + default: + /* if fds == NULL, select() can't return a result */ + svc_getreqset2(fds, svc_maxfd + 1); + free(fds); + } + } +} diff --git a/c/src/exec/librpc/src/rpc/svc_simple.c b/c/src/exec/librpc/src/rpc/svc_simple.c index e69de29bb2..ebc700257a 100644 --- a/c/src/exec/librpc/src/rpc/svc_simple.c +++ b/c/src/exec/librpc/src/rpc/svc_simple.c @@ -0,0 +1,151 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_simple.c,v 1.9 1999/08/28 00:00:50 peter Exp $"; +#endif + +/* + * svc_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct prog_lst { + char *(*p_progname)(); + int p_prognum; + int p_procnum; + xdrproc_t p_inproc, p_outproc; + struct prog_lst *p_nxt; +}; +static void universal(); +#define proglst ((struct prog_lst *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_simple_proglst) +#define pl ((struct prog_lst *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_simple_pl) +#define transp ((SVCXPRT *)((struct rtems_rpc_task_variables *)rtems_rpc_task_variables)->svc_simple_transp) + +int +registerrpc(prognum, versnum, procnum, progname, inproc, outproc) + int prognum, versnum, procnum; + char *(*progname)(); + xdrproc_t inproc, outproc; +{ + + if (procnum == NULLPROC) { + (void) fprintf(stderr, + "can't reassign procedure number %ld\n", NULLPROC); + return (-1); + } + if (transp == 0) { + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + (void) fprintf(stderr, "couldn't create an rpc server\n"); + return (-1); + } + } + (void) pmap_unset((u_long)prognum, (u_long)versnum); + if (!svc_register(transp, (u_long)prognum, (u_long)versnum, + universal, IPPROTO_UDP)) { + (void) fprintf(stderr, "couldn't register prog %d vers %d\n", + prognum, versnum); + return (-1); + } + pl = (struct prog_lst *)malloc(sizeof(struct prog_lst)); + if (pl == NULL) { + (void) fprintf(stderr, "registerrpc: out of memory\n"); + 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); +} + +static void +universal(rqstp, atransp) + struct svc_req *rqstp; + SVCXPRT *atransp; +{ + int prog, proc; + char *outdata; + char xdrbuf[UDPMSGSIZE]; + struct prog_lst *lpl; + + /* + * enforce "procnum 0 is echo" convention + */ + if (rqstp->rq_proc == NULLPROC) { + if (svc_sendreply(atransp, xdr_void, NULL) == FALSE) { + (void) fprintf(stderr, "xxx\n"); + exit(1); + } + return; + } + prog = rqstp->rq_prog; + proc = rqstp->rq_proc; + for (lpl = proglst; lpl != NULL; lpl = lpl->p_nxt) + if (lpl->p_prognum == prog && lpl->p_procnum == proc) { + /* decode arguments into a CLEAN buffer */ + memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */ + if (!svc_getargs(atransp, lpl->p_inproc, xdrbuf)) { + svcerr_decode(atransp); + return; + } + outdata = (*(lpl->p_progname))(xdrbuf); + if (outdata == NULL && lpl->p_outproc != xdr_void) + /* there was an error */ + return; + if (!svc_sendreply(atransp, lpl->p_outproc, outdata)) { + (void) fprintf(stderr, + "trouble replying to prog %d\n", + lpl->p_prognum); + exit(1); + } + /* free the decoded arguments */ + (void)svc_freeargs(atransp, lpl->p_inproc, xdrbuf); + return; + } + (void) fprintf(stderr, "never registered prog %d\n", prog); + exit(1); +} + diff --git a/c/src/exec/librpc/src/rpc/svc_tcp.c b/c/src/exec/librpc/src/rpc/svc_tcp.c index e69de29bb2..81ae27bead 100644 --- a/c/src/exec/librpc/src/rpc/svc_tcp.c +++ b/c/src/exec/librpc/src/rpc/svc_tcp.c @@ -0,0 +1,481 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_tcp.c,v 1.18 2000/01/27 23:06:41 jasone Exp $"; +#endif + +/* + * svc_tcp.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a tcp rendezvouser (a listner and connection establisher) + * and a record/tcp stream. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Ops vector for TCP/IP based rpc service handle + */ +static bool_t svctcp_recv(); +static enum xprt_stat svctcp_stat(); +static bool_t svctcp_getargs(); +static bool_t svctcp_reply(); +static bool_t svctcp_freeargs(); +static void svctcp_destroy(); + +static struct xp_ops svctcp_op = { + svctcp_recv, + svctcp_stat, + svctcp_getargs, + svctcp_reply, + svctcp_freeargs, + svctcp_destroy +}; + +/* + * Ops vector for TCP/IP rendezvous handler + */ +static bool_t rendezvous_request(); +static enum xprt_stat rendezvous_stat(); + +static struct xp_ops svctcp_rendezvous_op = { + rendezvous_request, + rendezvous_stat, + (bool_t (*)())abort, + (bool_t (*)())abort, + (bool_t (*)())abort, + svctcp_destroy +}; + +static int readtcp(), writetcp(); +static SVCXPRT *makefd_xprt(); + +struct tcp_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct tcp_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + +/* + * Usage: + * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) tcp based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svctcp_create + * binds it to an arbitrary port. The routine then starts a tcp + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since tcp streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svctcp_create(sock, sendsize, recvsize) + register int sock; + u_int sendsize; + u_int recvsize; +{ + bool_t madesock = FALSE; + register SVCXPRT *xprt; + register struct tcp_rendezvous *r; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + int on; + + if (sock == RPC_ANYSOCK) { + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + perror("svctcp_.c - udp socket creation problem"); + return ((SVCXPRT *)NULL); + } + madesock = TRUE; + } + on = 1; + if (ioctl(sock, FIONBIO, &on) < 0) { + perror("svc_tcp.c - cannot turn on non-blocking mode"); + if (madesock) + (void)_close(sock); + return ((SVCXPRT *)NULL); + } + memset(&addr, 0, sizeof (addr)); + addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_family = AF_INET; + if (bindresvport(sock, &addr)) { + addr.sin_port = 0; + (void)bind(sock, (struct sockaddr *)&addr, len); + } + if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) || + (listen(sock, 2) != 0)) { + perror("svctcp_.c - cannot getsockname or listen"); + if (madesock) + (void)_close(sock); + return ((SVCXPRT *)NULL); + } + r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r)); + if (r == NULL) { + (void) fprintf(stderr, "svctcp_create: out of memory\n"); + return (NULL); + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + if (xprt == NULL) { + (void) fprintf(stderr, "svctcp_create: out of memory\n"); + return (NULL); + } + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t)r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svctcp_rendezvous_op; + xprt->xp_port = ntohs(addr.sin_port); + xprt->xp_sock = sock; + xprt_register(xprt); + return (xprt); +} + +/* + * Like svtcp_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcfd_create(fd, sendsize, recvsize) + int fd; + u_int sendsize; + u_int recvsize; +{ + + return (makefd_xprt(fd, sendsize, recvsize)); +} + +static SVCXPRT * +makefd_xprt(fd, sendsize, recvsize) + int fd; + u_int sendsize; + u_int recvsize; +{ + register SVCXPRT *xprt; + register struct tcp_conn *cd; + + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + if (xprt == (SVCXPRT *)NULL) { + (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); + goto done; + } + cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn)); + if (cd == (struct tcp_conn *)NULL) { + (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); + mem_free((char *) xprt, sizeof(SVCXPRT)); + xprt = (SVCXPRT *)NULL; + goto done; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create(&(cd->xdrs), sendsize, recvsize, + (caddr_t)xprt, readtcp, writetcp); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t)cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svctcp_op; /* truely deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register(xprt); + done: + return (xprt); +} + +static bool_t +rendezvous_request(xprt) + register SVCXPRT *xprt; +{ + int sock; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + int len; + int off; + + r = (struct tcp_rendezvous *)xprt->xp_p1; + again: + len = sizeof(struct sockaddr_in); + if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, + &len)) < 0) { + if (errno == EINTR) + goto again; + return (FALSE); + } + /* + * Guard against FTP bounce attacks. + */ + if (addr.sin_port == htons(20)) { + _close(sock); + return (FALSE); + } + /* + * The listening socket is in FIONBIO mode and we inherit it. + */ + off = 0; + if (ioctl(sock, FIONBIO, &off) < 0) { + _close(sock); + return (FALSE); + } + /* + * make a new transporter (re-uses xprt) + */ + xprt = makefd_xprt(sock, r->sendsize, r->recvsize); + xprt->xp_raddr = addr; + xprt->xp_addrlen = len; + return (FALSE); /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat() +{ + + return (XPRT_IDLE); +} + +static void +svctcp_destroy(xprt) + register SVCXPRT *xprt; +{ + register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1; + + xprt_unregister(xprt); + (void)_close(xprt->xp_sock); + if (xprt->xp_port != 0) { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } else { + /* an actual connection socket */ + XDR_DESTROY(&(cd->xdrs)); + } + mem_free((caddr_t)cd, sizeof(struct tcp_conn)); + mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + +/* + * All read operations timeout after 35 seconds. + * A timeout is fatal for the connection. + */ +static struct timeval wait_per_try = { 35, 0 }; + +/* + * reads data from the tcp conection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + * + * Note: we have to be careful here not to allow ourselves to become + * blocked too long in this routine. While we're waiting for data from one + * client, another client may be trying to connect. To avoid this situation, + * some code from svc_run() is transplanted here: the select() loop checks + * all RPC descriptors including the one we want and calls svc_getreqset2() + * to handle new requests if any are detected. + */ +static int +readtcp(xprt, buf, len) + register SVCXPRT *xprt; + caddr_t buf; + register int len; +{ + register int sock = xprt->xp_sock; + struct timeval start, delta, tv; + struct timeval tmp1, tmp2; + fd_set *fds; + + delta = wait_per_try; + fds = NULL; + gettimeofday(&start, NULL); + do { + int bytes = sizeof (fd_set); + 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: + if (errno != EINTR) + goto fatal_err; + gettimeofday(&tmp1, NULL); + timersub(&tmp1, &start, &tmp2); + timersub(&wait_per_try, &tmp2, &tmp1); + if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) + goto fatal_err; + delta = tmp1; + continue; + case 0: + goto fatal_err; + default: + if (!FD_ISSET(sock, fds)) { + svc_getreqset2(fds, svc_maxfd + 1); + gettimeofday(&tmp1, NULL); + timersub(&tmp1, &start, &tmp2); + timersub(&wait_per_try, &tmp2, &tmp1); + if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) + goto fatal_err; + delta = tmp1; + continue; + } + } + } while (!FD_ISSET(sock, fds)); + if ((len = _read(sock, buf, len)) > 0) { + if (fds != NULL) + free(fds); + return (len); + } +fatal_err: + ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; + if (fds != NULL) + free(fds); + return (-1); +} + +/* + * writes data to the tcp connection. + * Any error is fatal and the connection is closed. + */ +static int +writetcp(xprt, buf, len) + register SVCXPRT *xprt; + caddr_t buf; + int len; +{ + register int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = _write(xprt->xp_sock, buf, cnt)) < 0) { + ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = + XPRT_DIED; + return (-1); + } + } + return (len); +} + +static enum xprt_stat +svctcp_stat(xprt) + SVCXPRT *xprt; +{ + register struct tcp_conn *cd = + (struct tcp_conn *)(xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return (XPRT_DIED); + if (! xdrrec_eof(&(cd->xdrs))) + return (XPRT_MOREREQS); + return (XPRT_IDLE); +} + +static bool_t +svctcp_recv(xprt, msg) + SVCXPRT *xprt; + register struct rpc_msg *msg; +{ + register struct tcp_conn *cd = + (struct tcp_conn *)(xprt->xp_p1); + register XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + (void)xdrrec_skiprecord(xdrs); + if (xdr_callmsg(xdrs, msg)) { + cd->x_id = msg->rm_xid; + return (TRUE); + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return (FALSE); +} + +static bool_t +svctcp_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svctcp_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register XDR *xdrs = + &(((struct tcp_conn *)(xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static bool_t +svctcp_reply(xprt, msg) + SVCXPRT *xprt; + register struct rpc_msg *msg; +{ + register struct tcp_conn *cd = + (struct tcp_conn *)(xprt->xp_p1); + register XDR *xdrs = &(cd->xdrs); + register bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg(xdrs, msg); + (void)xdrrec_endofrecord(xdrs, TRUE); + return (stat); +} diff --git a/c/src/exec/librpc/src/rpc/svc_udp.c b/c/src/exec/librpc/src/rpc/svc_udp.c index e69de29bb2..e5d90a184f 100644 --- a/c/src/exec/librpc/src/rpc/svc_udp.c +++ b/c/src/exec/librpc/src/rpc/svc_udp.c @@ -0,0 +1,480 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_udp.c,v 1.13 2000/01/27 23:06:41 jasone Exp $"; +#endif + +/* + * svc_udp.c, + * Server side for UDP/IP based RPC. (Does some caching in the hopes of + * achieving execute-at-most-once semantics.) + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#define MAX(a, b) ((a > b) ? a : b) + +static bool_t svcudp_recv(); +static bool_t svcudp_reply(); +static enum xprt_stat svcudp_stat(); +static bool_t svcudp_getargs(); +static bool_t svcudp_freeargs(); +static void svcudp_destroy(); +static void cache_set __P((SVCXPRT *, u_long)); +static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, u_long *)); + +static struct xp_ops svcudp_op = { + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char * su_cache; /* cached data, NULL if no cache */ +}; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate(sock, sendsz, recvsz) + register int sock; + u_int sendsz, recvsz; +{ + bool_t madesock = FALSE; + register SVCXPRT *xprt; + register struct svcudp_data *su; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + + if (sock == RPC_ANYSOCK) { + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("svcudp_create: socket creation problem"); + return ((SVCXPRT *)NULL); + } + madesock = TRUE; + } + memset((char *)&addr, 0, sizeof (addr)); + addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_family = AF_INET; + if (bindresvport(sock, &addr)) { + addr.sin_port = 0; + (void)bind(sock, (struct sockaddr *)&addr, len); + } + if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { + perror("svcudp_create - cannot getsockname"); + if (madesock) + (void)_close(sock); + return ((SVCXPRT *)NULL); + } + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + if (xprt == NULL) { + (void)fprintf(stderr, "svcudp_create: out of memory\n"); + return (NULL); + } + su = (struct svcudp_data *)mem_alloc(sizeof(*su)); + if (su == NULL) { + (void)fprintf(stderr, "svcudp_create: out of memory\n"); + return (NULL); + } + su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4; + if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) { + (void)fprintf(stderr, "svcudp_create: out of memory\n"); + return (NULL); + } + xdrmem_create( + &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); + su->su_cache = NULL; + xprt->xp_p2 = (caddr_t)su; + xprt->xp_verf.oa_base = su->su_verfbody; + xprt->xp_ops = &svcudp_op; + xprt->xp_port = ntohs(addr.sin_port); + xprt->xp_sock = sock; + xprt_register(xprt); + return (xprt); +} + +SVCXPRT * +svcudp_create(sock) + int sock; +{ + + return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE)); +} + +static enum xprt_stat +svcudp_stat(xprt) + SVCXPRT *xprt; +{ + + return (XPRT_IDLE); +} + +static bool_t +svcudp_recv(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int rlen; + char *reply; + u_long replylen; + + again: + xprt->xp_addrlen = sizeof(struct sockaddr_in); + rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, + 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); + if (rlen == -1 && errno == EINTR) + goto again; + if (rlen == -1 || rlen < 4*sizeof(u_int32_t)) + return (FALSE); + xdrs->x_op = XDR_DECODE; + XDR_SETPOS(xdrs, 0); + if (! xdr_callmsg(xdrs, msg)) + return (FALSE); + su->su_xid = msg->rm_xid; + if (su->su_cache != NULL) { + if (cache_get(xprt, msg, &reply, &replylen)) { + (void) sendto(xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen); + return (TRUE); + } + } + return (TRUE); +} + +static bool_t +svcudp_reply(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int slen; + register bool_t stat = FALSE; + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg(xdrs, msg)) { + slen = (int)XDR_GETPOS(xdrs); + if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0, + (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen) + == slen) { + stat = TRUE; + if (su->su_cache && slen >= 0) { + cache_set(xprt, (u_long) slen); + } + } + } + return (stat); +} + +static bool_t +svcudp_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); +} + +static bool_t +svcudp_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register XDR *xdrs = &(su_data(xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static void +svcudp_destroy(xprt) + register SVCXPRT *xprt; +{ + register struct svcudp_data *su = su_data(xprt); + + xprt_unregister(xprt); + (void)_close(xprt->xp_sock); + XDR_DESTROY(&(su->su_xdrs)); + mem_free(rpc_buffer(xprt), su->su_iosz); + mem_free((caddr_t)su, sizeof(struct svcudp_data)); + mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + + +/***********this could be a separate file*********************/ + +/* + * Fifo cache for udp server + * Copies pointers to reply buffers into fifo cache + * Buffers are sent again if retransmissions are detected. + */ + +#define SPARSENESS 4 /* 75% sparse */ + +#define CACHE_PERROR(msg) \ + (void) fprintf(stderr,"%s\n", msg) + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define BZERO(addr, type, size) \ + memset((char *) addr, 0, sizeof(type) * (int) (size)) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char * cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; +}; + + + +/* + * The entire cache + */ +struct udp_cache { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ +}; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ +int svcudp_enablecache(transp, size) + SVCXPRT *transp; + u_long size; +{ + struct svcudp_data *su = su_data(transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) { + CACHE_PERROR("enablecache: cache already enabled"); + return(0); + } + uc = ALLOC(struct udp_cache, 1); + if (uc == NULL) { + CACHE_PERROR("enablecache: could not allocate cache"); + return(0); + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) { + CACHE_PERROR("enablecache: could not allocate cache data"); + return(0); + } + BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC(cache_ptr, size); + if (uc->uc_fifo == NULL) { + CACHE_PERROR("enablecache: could not allocate cache fifo"); + return(0); + } + BZERO(uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return(1); +} + + +/* + * Set an entry in the cache + */ +static void +cache_set(xprt, replylen) + SVCXPRT *xprt; + u_long replylen; +{ + register cache_ptr victim; + register cache_ptr *vicp; + register struct svcudp_data *su = su_data(xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) { + loc = CACHE_LOC(xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) { + CACHE_PERROR("cache_set: victim not found"); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } else { + victim = ALLOC(struct cache_node, 1); + if (victim == NULL) { + CACHE_PERROR("cache_set: victim alloc failed"); + return; + } + newbuf = mem_alloc(su->su_iosz); + if (newbuf == NULL) { + CACHE_PERROR("cache_set: could not allocate new rpc_buffer"); + return; + } + } + + /* + * Store it away + */ + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer(xprt); + rpc_buffer(xprt) = newbuf; + xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE); + victim->cache_xid = su->su_xid; + victim->cache_proc = uc->uc_proc; + victim->cache_vers = uc->uc_vers; + victim->cache_prog = uc->uc_prog; + victim->cache_addr = uc->uc_addr; + loc = CACHE_LOC(xprt, victim->cache_xid); + victim->cache_next = uc->uc_entries[loc]; + uc->uc_entries[loc] = victim; + uc->uc_fifo[uc->uc_nextvictim++] = victim; + uc->uc_nextvictim %= uc->uc_size; +} + +/* + * Try to get an entry from the cache + * return 1 if found, 0 if not found + */ +static int +cache_get(xprt, msg, replyp, replylenp) + SVCXPRT *xprt; + struct rpc_msg *msg; + char **replyp; + u_long *replylenp; +{ + u_int loc; + register cache_ptr ent; + register struct svcudp_data *su = su_data(xprt); + register struct udp_cache *uc = (struct udp_cache *) su->su_cache; + +# define EQADDR(a1, a2) (memcmp(&a1, &a2, sizeof(a1)) == 0) + + loc = CACHE_LOC(xprt, su->su_xid); + for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) { + if (ent->cache_xid == su->su_xid && + ent->cache_proc == uc->uc_proc && + ent->cache_vers == uc->uc_vers && + ent->cache_prog == uc->uc_prog && + EQADDR(ent->cache_addr, uc->uc_addr)) { + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + return(1); + } + } + /* + * Failed to find entry + * Remember a few things so we can do a set later + */ + uc->uc_proc = msg->rm_call.cb_proc; + uc->uc_vers = msg->rm_call.cb_vers; + uc->uc_prog = msg->rm_call.cb_prog; + uc->uc_addr = xprt->xp_raddr; + return(0); +} + diff --git a/c/src/exec/librpc/src/rpc/svc_unix.c b/c/src/exec/librpc/src/rpc/svc_unix.c index e69de29bb2..b0f3175c0e 100644 --- a/c/src/exec/librpc/src/rpc/svc_unix.c +++ b/c/src/exec/librpc/src/rpc/svc_unix.c @@ -0,0 +1,527 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_unix.c,v 1.7 2000/01/27 23:06:42 jasone Exp $"; +#endif + +/* + * svc_unix.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a unix rendezvouser (a listner and connection establisher) + * and a record/unix stream. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Ops vector for AF_UNIX based rpc service handle + */ +static bool_t svcunix_recv(); +static enum xprt_stat svcunix_stat(); +static bool_t svcunix_getargs(); +static bool_t svcunix_reply(); +static bool_t svcunix_freeargs(); +static void svcunix_destroy(); + +static struct xp_ops svcunix_op = { + svcunix_recv, + svcunix_stat, + svcunix_getargs, + svcunix_reply, + svcunix_freeargs, + svcunix_destroy +}; + +/* + * Ops vector for TCP/IP rendezvous handler + */ +static bool_t rendezvous_request(); +static enum xprt_stat rendezvous_stat(); + +static struct xp_ops svcunix_rendezvous_op = { + rendezvous_request, + rendezvous_stat, + (bool_t (*)())abort, + (bool_t (*)())abort, + (bool_t (*)())abort, + svcunix_destroy +}; + +static int readunix(), writeunix(); +static SVCXPRT *makefd_xprt(); + +struct unix_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct unix_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + + +struct cmessage { + struct cmsghdr cmsg; + struct cmsgcred cmcred; +}; + +static struct cmessage cm; + +static int __msgread(sock, buf, cnt) + int sock; + void *buf; + size_t cnt; +{ + struct iovec iov[1]; + struct msghdr msg; + + bzero((char *)&cm, sizeof(cm)); + iov[0].iov_base = buf; + iov[0].iov_len = cnt; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = (caddr_t)&cm; + msg.msg_controllen = sizeof(struct cmessage); + msg.msg_flags = 0; + + return(recvmsg(sock, &msg, 0)); +} + +static int __msgwrite(sock, buf, cnt) + int sock; + void *buf; + size_t cnt; +{ + struct iovec iov[1]; + struct msghdr msg; + + bzero((char *)&cm, sizeof(cm)); + iov[0].iov_base = buf; + iov[0].iov_len = cnt; + + cm.cmsg.cmsg_type = SCM_CREDS; + cm.cmsg.cmsg_level = SOL_SOCKET; + cm.cmsg.cmsg_len = sizeof(struct cmessage); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = (caddr_t)&cm; + msg.msg_controllen = sizeof(struct cmessage); + msg.msg_flags = 0; + + return(sendmsg(sock, &msg, 0)); +} + +/* + * Usage: + * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) unix based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcunix_create + * binds it to an arbitrary port. The routine then starts a unix + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since unix streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svcunix_create(sock, sendsize, recvsize, path) + register int sock; + u_int sendsize; + u_int recvsize; + char *path; +{ + bool_t madesock = FALSE; + register SVCXPRT *xprt; + register struct unix_rendezvous *r; + struct sockaddr_un addr; + int len = sizeof(struct sockaddr_un); + + if (sock == RPC_ANYSOCK) { + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("svc_unix.c - AF_UNIX socket creation problem"); + return ((SVCXPRT *)NULL); + } + madesock = TRUE; + } + memset(&addr, 0, sizeof (addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, path); + len = strlen(addr.sun_path) + sizeof(addr.sun_family) + + sizeof(addr.sun_len) + 1; + addr.sun_len = len; + + bind(sock, (struct sockaddr *)&addr, len); + + if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) || + (listen(sock, 2) != 0)) { + perror("svc_unix.c - cannot getsockname or listen"); + if (madesock) + (void)_close(sock); + return ((SVCXPRT *)NULL); + } + r = (struct unix_rendezvous *)mem_alloc(sizeof(*r)); + if (r == NULL) { + (void) fprintf(stderr, "svcunix_create: out of memory\n"); + return (NULL); + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + if (xprt == NULL) { + (void) fprintf(stderr, "svcunix_create: out of memory\n"); + return (NULL); + } + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t)r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svcunix_rendezvous_op; + xprt->xp_port = -1 /*ntohs(addr.sin_port)*/; + xprt->xp_sock = sock; + xprt_register(xprt); + return (xprt); +} + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcunixfd_create(fd, sendsize, recvsize) + int fd; + u_int sendsize; + u_int recvsize; +{ + + return (makefd_xprt(fd, sendsize, recvsize)); +} + +static SVCXPRT * +makefd_xprt(fd, sendsize, recvsize) + int fd; + u_int sendsize; + u_int recvsize; +{ + register SVCXPRT *xprt; + register struct unix_conn *cd; + + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + if (xprt == (SVCXPRT *)NULL) { + (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n"); + goto done; + } + cd = (struct unix_conn *)mem_alloc(sizeof(struct unix_conn)); + if (cd == (struct unix_conn *)NULL) { + (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n"); + mem_free((char *) xprt, sizeof(SVCXPRT)); + xprt = (SVCXPRT *)NULL; + goto done; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create(&(cd->xdrs), sendsize, recvsize, + (caddr_t)xprt, readunix, writeunix); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t)cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svcunix_op; /* truely deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register(xprt); + done: + return (xprt); +} + +static bool_t +rendezvous_request(xprt) + register SVCXPRT *xprt; +{ + int sock; + struct unix_rendezvous *r; + struct sockaddr_un addr; + struct sockaddr_in in_addr; + int len; + + r = (struct unix_rendezvous *)xprt->xp_p1; + again: + len = sizeof(struct sockaddr_in); + if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, + &len)) < 0) { + if (errno == EINTR) + goto again; + return (FALSE); + } + + /* + * make a new transporter (re-uses xprt) + */ + bzero((char *)&in_addr, sizeof(in_addr)); + in_addr.sin_family = AF_UNIX; + xprt = makefd_xprt(sock, r->sendsize, r->recvsize); + xprt->xp_raddr = in_addr; + xprt->xp_addrlen = len; + return (FALSE); /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat() +{ + + return (XPRT_IDLE); +} + +static void +svcunix_destroy(xprt) + register SVCXPRT *xprt; +{ + register struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1; + + xprt_unregister(xprt); + (void)_close(xprt->xp_sock); + if (xprt->xp_port != 0) { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } else { + /* an actual connection socket */ + XDR_DESTROY(&(cd->xdrs)); + } + mem_free((caddr_t)cd, sizeof(struct unix_conn)); + mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + +/* + * All read operations timeout after 35 seconds. + * A timeout is fatal for the connection. + */ +static struct timeval wait_per_try = { 35, 0 }; + +/* + * reads data from the unix conection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + * + * Note: we have to be careful here not to allow ourselves to become + * blocked too long in this routine. While we're waiting for data from one + * client, another client may be trying to connect. To avoid this situation, + * some code from svc_run() is transplanted here: the select() loop checks + * all RPC descriptors including the one we want and calls svc_getreqset2() + * to handle new requests if any are detected. + */ +static int +readunix(xprt, buf, len) + register SVCXPRT *xprt; + caddr_t buf; + register int len; +{ + register int sock = xprt->xp_sock; + struct timeval start, delta, tv; + struct timeval tmp1, tmp2; + fd_set *fds; + + delta = wait_per_try; + fds = NULL; + gettimeofday(&start, NULL); + do { + int bytes = sizeof (fd_set); + 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: + if (errno != EINTR) + goto fatal_err; + gettimeofday(&tmp1, NULL); + timersub(&tmp1, &start, &tmp2); + timersub(&wait_per_try, &tmp2, &tmp1); + if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) + goto fatal_err; + delta = tmp1; + continue; + case 0: + goto fatal_err; + default: + if (!FD_ISSET(sock, fds)) { + svc_getreqset2(fds, svc_maxfd + 1); + gettimeofday(&tmp1, NULL); + timersub(&tmp1, &start, &tmp2); + timersub(&wait_per_try, &tmp2, &tmp1); + if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) + goto fatal_err; + delta = tmp1; + continue; + } + } + } while (!FD_ISSET(sock, fds)); + if ((len = __msgread(sock, buf, len)) > 0) { + if (fds != NULL) + free(fds); + return (len); + } +fatal_err: + ((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; + if (fds != NULL) + free(fds); + return (-1); +} + +/* + * writes data to the unix connection. + * Any error is fatal and the connection is closed. + */ +static int +writeunix(xprt, buf, len) + register SVCXPRT *xprt; + caddr_t buf; + int len; +{ + register int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = __msgwrite(xprt->xp_sock, buf, cnt)) < 0) { + ((struct unix_conn *)(xprt->xp_p1))->strm_stat = + XPRT_DIED; + return (-1); + } + } + return (len); +} + +static enum xprt_stat +svcunix_stat(xprt) + SVCXPRT *xprt; +{ + register struct unix_conn *cd = + (struct unix_conn *)(xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return (XPRT_DIED); + if (! xdrrec_eof(&(cd->xdrs))) + return (XPRT_MOREREQS); + return (XPRT_IDLE); +} + +static bool_t +svcunix_recv(xprt, msg) + SVCXPRT *xprt; + register struct rpc_msg *msg; +{ + register struct unix_conn *cd = + (struct unix_conn *)(xprt->xp_p1); + register XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + (void)xdrrec_skiprecord(xdrs); + if (xdr_callmsg(xdrs, msg)) { + cd->x_id = msg->rm_xid; + /* set up verifiers */ + msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX; + msg->rm_call.cb_verf.oa_base = (caddr_t)&cm; + msg->rm_call.cb_verf.oa_length = sizeof(cm); + return (TRUE); + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return (FALSE); +} + +static bool_t +svcunix_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return ((*xdr_args)(&(((struct unix_conn *)(xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svcunix_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register XDR *xdrs = + &(((struct unix_conn *)(xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static bool_t +svcunix_reply(xprt, msg) + SVCXPRT *xprt; + register struct rpc_msg *msg; +{ + register struct unix_conn *cd = + (struct unix_conn *)(xprt->xp_p1); + register XDR *xdrs = &(cd->xdrs); + register bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg(xdrs, msg); + (void)xdrrec_endofrecord(xdrs, TRUE); + return (stat); +} diff --git a/c/src/exec/librpc/src/xdr/Makefile.am b/c/src/exec/librpc/src/xdr/Makefile.am index e69de29bb2..222a4fe3f5 100644 --- a/c/src/exec/librpc/src/xdr/Makefile.am +++ b/c/src/exec/librpc/src/xdr/Makefile.am @@ -0,0 +1,44 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 no-installman + +LIBNAME = libxdr +LIB = $(ARCH)/$(LIBNAME).a + +C_FILES = xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \ + xdr_sizeof.c xdr_stdio.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../automake/lib.am + +noinst_MANS = xdr.3 + +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a + +# +# Add local stuff here using += +# + +AM_CPPFLAGS += '-D__P(x)=x' + +$(LIB): $(OBJS) + $(make-library) + +$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) + $(INSTALL_DATA) $< $@ + +if HAS_NETWORKING +man_MANS = $(noinst_MANS) +all-local: $(ARCH) $(OBJS) $(TMPINSTALL_FILES) +endif + +.PRECIOUS: $(LIB) + +EXTRA_DIST = $(C_FILES) $(noinst_MANS) + +include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/librpc/src/xdr/xdr.3 b/c/src/exec/librpc/src/xdr/xdr.3 index e69de29bb2..c1cdb11015 100644 --- a/c/src/exec/librpc/src/xdr/xdr.3 +++ b/c/src/exec/librpc/src/xdr/xdr.3 @@ -0,0 +1,837 @@ +.\" @(#)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 2000/03/02 09:14:05 sheldonh Exp $ +.\" +.TH XDR 3 "16 February 1988" +.SH NAME +xdr \- library routines for external data representation +.SH SYNOPSIS AND DESCRIPTION +.LP +These routines allow C programmers to describe +arbitrary data structures in a machine-independent fashion. +Data for remote procedure calls are transmitted using these +routines. +.LP +.ft B +.nf +.sp .5 +xdr_array(xdrs, arrp, sizep, maxsize, elsize, elproc) +\s-1XDR\s0 *xdrs; +char **arrp; +u_int *sizep, maxsize, elsize; +xdrproc_t elproc; +.fi +.ft R +.IP +A filter primitive that translates between variable-length +arrays +and their corresponding external representations. +The +parameter +.I arrp +is the address of the pointer to the array, while +.I sizep +is the address of the element count of the array; +this element count cannot exceed +.IR maxsize . +The parameter +.I elsize +is the +.I sizeof +each of the array's elements, and +.I elproc +is an +.SM XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_bool(xdrs, bp) +\s-1XDR\s0 *xdrs; +bool_t *bp; +.fi +.ft R +.IP +A filter primitive that translates between booleans (C +integers) +and their external representations. +When encoding data, this +filter produces values of either one or zero. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +xdr_bytes(xdrs, sp, sizep, maxsize) +\s-1XDR\s0 *xdrs; +char **sp; +u_int *sizep, maxsize; +.fi +.ft R +.IP +A filter primitive that translates between counted byte +strings and their external representations. +The parameter +.I sp +is the address of the string pointer. +The length of the +string is located at address +.IR sizep ; +strings cannot be longer than +.IR maxsize . +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_char(xdrs, cp) +\s-1XDR\s0 *xdrs; +char *cp; +.fi +.ft R +.IP +A filter primitive that translates between C characters +and their external representations. +This routine returns one if it succeeds, zero otherwise. +Note: encoded characters are not packed, and occupy 4 bytes +each. +For arrays of characters, it is worthwhile to +consider +.BR xdr_bytes(\|) , +.B xdr_opaque(\|) +or +.BR xdr_string(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +xdr_destroy(xdrs) +\s-1XDR\s0 *xdrs; +.fi +.ft R +.IP +A macro that invokes the destroy routine associated with the +.SM XDR +stream, +.IR xdrs . +Destruction usually involves freeing private data structures +associated with the stream. Using +.I xdrs +after invoking +.B xdr_destroy(\|) +is undefined. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_double(xdrs, dp) +\s-1XDR\s0 *xdrs; +double *dp; +.fi +.ft R +.IP +A filter primitive that translates between C +.B double +precision numbers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_enum(xdrs, ep) +\s-1XDR\s0 *xdrs; +enum_t *ep; +.fi +.ft R +.IP +A filter primitive that translates between C +.BR enum s +(actually integers) and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_float(xdrs, fp) +\s-1XDR\s0 *xdrs; +float *fp; +.fi +.ft R +.IP +A filter primitive that translates between C +.BR float s +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +void +xdr_free(proc, objp) +xdrproc_t proc; +char *objp; +.fi +.ft R +.IP +Generic freeing routine. +The first argument is the +.SM XDR +routine for the object being freed. +The second argument +is a pointer to the object itself. +Note: the pointer passed +to this routine is +.I not +freed, but what it points to +.I is +freed (recursively). +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +u_int +xdr_getpos(xdrs) +\s-1XDR\s0 *xdrs; +.fi +.ft R +.IP +A macro that invokes the get-position routine +associated with the +.SM XDR +stream, +.IR xdrs . +The routine returns an unsigned integer, +which indicates the position of the +.SM XDR +byte stream. +A desirable feature of +.SM XDR +streams is that simple arithmetic works with this number, +although the +.SM XDR +stream instances need not guarantee this. +.br +.if t .ne 4 +.LP +.ft B +.nf +.sp .5 +.br +long * +xdr_inline(xdrs, len) +\s-1XDR\s0 *xdrs; +int len; +.fi +.ft R +.IP +A macro that invokes the in-line routine associated with the +.SM XDR +stream, +.IR xdrs . +The routine returns a pointer +to a contiguous piece of the stream's buffer; +.I len +is the byte length of the desired buffer. +Note: pointer is cast to +.BR "long *" . +.IP +Warning: +.B xdr_inline(\|) +may return +.SM NULL +(0) +if it cannot allocate a contiguous piece of a buffer. +Therefore the behavior may vary among stream instances; +it exists for the sake of efficiency. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_int(xdrs, ip) +\s-1XDR\s0 *xdrs; +int *ip; +.fi +.ft R +.IP +A filter primitive that translates between C integers +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_long(xdrs, lp) +\s-1XDR\s0 *xdrs; +long *lp; +.fi +.ft R +.IP +A filter primitive that translates between C +.B long +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 12 +.LP +.ft B +.nf +.sp .5 +void +xdrmem_create(xdrs, addr, size, op) +\s-1XDR\s0 *xdrs; +char *addr; +u_int size; +enum xdr_op op; +.fi +.ft R +.IP +This routine initializes the +.SM XDR +stream object pointed to by +.IR xdrs . +The stream's data is written to, or read from, +a chunk of memory at location +.I addr +whose length is no more than +.I size +bytes long. The +.I op +determines the direction of the +.SM XDR +stream +(either +.BR \s-1XDR_ENCODE\s0 , +.BR \s-1XDR_DECODE\s0 , +or +.BR \s-1XDR_FREE\s0 ). +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +xdr_opaque(xdrs, cp, cnt) +\s-1XDR\s0 *xdrs; +char *cp; +u_int cnt; +.fi +.ft R +.IP +A filter primitive that translates between fixed size opaque +data +and its external representation. +The parameter +.I cp +is the address of the opaque object, and +.I cnt +is its size in bytes. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +xdr_pointer(xdrs, objpp, objsize, xdrobj) +\s-1XDR\s0 *xdrs; +char **objpp; +u_int objsize; +xdrproc_t xdrobj; +.fi +.ft R +.IP +Like +.B xdr_reference(\|) +execpt that it serializes +.SM NULL +pointers, whereas +.B xdr_reference(\|) +does not. Thus, +.B xdr_pointer(\|) +can represent +recursive data structures, such as binary trees or +linked lists. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +void +xdrrec_create(xdrs, sendsize, recvsize, handle, readit, writeit) +\s-1XDR\s0 *xdrs; +u_int sendsize, recvsize; +char *handle; +int (*readit) (\|), (*writeit) (\|); +.fi +.ft R +.IP +This routine initializes the +.SM XDR +stream object pointed to by +.IR xdrs . +The stream's data is written to a buffer of size +.IR sendsize ; +a value of zero indicates the system should use a suitable +default. +The stream's data is read from a buffer of size +.IR recvsize ; +it too can be set to a suitable default by passing a zero +value. +When a stream's output buffer is full, +.I writeit +is called. Similarly, when a stream's input buffer is empty, +.I readit +is called. The behavior of these two routines is similar to +the +system calls +.B read +and +.BR write , +except that +.I handle +is passed to the former routines as the first parameter. +Note: the +.SM XDR +stream's +.I op +field must be set by the caller. +.IP +Warning: this +.SM XDR +stream implements an intermediate record stream. +Therefore there are additional bytes in the stream +to provide record boundary information. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +xdrrec_endofrecord(xdrs, sendnow) +\s-1XDR\s0 *xdrs; +int sendnow; +.fi +.ft R +.IP +This routine can be invoked only on +streams created by +.BR xdrrec_create(\|) . +The data in the output buffer is marked as a completed +record, +and the output buffer is optionally written out if +.I sendnow +is non-zero. +This routine returns one if it succeeds, zero +otherwise. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdrrec_eof(xdrs) +\s-1XDR\s0 *xdrs; +int empty; +.fi +.ft R +.IP +This routine can be invoked only on +streams created by +.BR xdrrec_create(\|) . +After consuming the rest of the current record in the stream, +this routine returns one if the stream has no more input, +zero otherwise. +.br +.if t .ne 3 +.LP +.ft B +.nf +.sp .5 +xdrrec_skiprecord(xdrs) +\s-1XDR\s0 *xdrs; +.fi +.ft R +.IP +This routine can be invoked only on +streams created by +.BR xdrrec_create(\|) . +It tells the +.SM XDR +implementation that the rest of the current record +in the stream's input buffer should be discarded. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +xdr_reference(xdrs, pp, size, proc) +\s-1XDR\s0 *xdrs; +char **pp; +u_int size; +xdrproc_t proc; +.fi +.ft R +.IP +A primitive that provides pointer chasing within structures. +The parameter +.I pp +is the address of the pointer; +.I size +is the +.I sizeof +the structure that +.I *pp +points to; and +.I proc +is an +.SM XDR +procedure that filters the structure +between its C form and its external representation. +This routine returns one if it succeeds, zero otherwise. +.IP +Warning: this routine does not understand +.SM NULL +pointers. +Use +.B xdr_pointer(\|) +instead. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +xdr_setpos(xdrs, pos) +\s-1XDR\s0 *xdrs; +u_int pos; +.fi +.ft R +.IP +A macro that invokes the set position routine associated with +the +.SM XDR +stream +.IR xdrs . +The parameter +.I pos +is a position value obtained from +.BR xdr_getpos(\|) . +This routine returns one if the +.SM XDR +stream could be repositioned, +and zero otherwise. +.IP +Warning: it is difficult to reposition some types of +.SM XDR +streams, so this routine may fail with one +type of stream and succeed with another. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_short(xdrs, sp) +\s-1XDR\s0 *xdrs; +short *sp; +.fi +.ft R +.IP +A filter primitive that translates between C +.B short +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +void +xdrstdio_create(xdrs, file, op) +\s-1XDR\s0 *xdrs; +\s-1FILE\s0 *file; +enum xdr_op op; +.fi +.ft R +.IP +This routine initializes the +.SM XDR +stream object pointed to by +.IR xdrs . +The +.SM XDR +stream data is written to, or read from, the Standard +.B I/O +stream +.IR file . +The parameter +.I op +determines the direction of the +.SM XDR +stream (either +.BR \s-1XDR_ENCODE\s0 , +.BR \s-1XDR_DECODE\s0 , +or +.BR \s-1XDR_FREE\s0 ). +.IP +Warning: the destroy routine associated with such +.SM XDR +streams calls +.B fflush(\|) +on the +.I file +stream, but never +.BR fclose(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +xdr_string(xdrs, sp, maxsize) +\s-1XDR\s0 +*xdrs; +char **sp; +u_int maxsize; +.fi +.ft R +.IP +A filter primitive that translates between C strings and +their +corresponding external representations. +Strings cannot be longer than +.IR maxsize . +Note: +.I sp +is the address of the string's pointer. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_u_char(xdrs, ucp) +\s-1XDR\s0 *xdrs; +unsigned char *ucp; +.fi +.ft R +.IP +A filter primitive that translates between +.B unsigned +C characters and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +xdr_u_int(xdrs, up) +\s-1XDR\s0 *xdrs; +unsigned *up; +.fi +.ft R +.IP +A filter primitive that translates between C +.B unsigned +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_u_long(xdrs, ulp) +\s-1XDR\s0 *xdrs; +unsigned long *ulp; +.fi +.ft R +.IP +A filter primitive that translates between C +.B "unsigned long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_u_short(xdrs, usp) +\s-1XDR\s0 *xdrs; +unsigned short *usp; +.fi +.ft R +.IP +A filter primitive that translates between C +.B "unsigned short" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 16 +.LP +.ft B +.nf +.sp .5 +xdr_union(xdrs, dscmp, unp, choices, dfault) +\s-1XDR\s0 *xdrs; +int *dscmp; +char *unp; +struct xdr_discrim *choices; +bool_t (*defaultarm) (\|); /* may equal \s-1NULL\s0 */ +.fi +.ft R +.IP +A filter primitive that translates between a discriminated C +.B union +and its corresponding external representation. +It first +translates the discriminant of the union located at +.IR dscmp . +This discriminant is always an +.BR enum_t . +Next the union located at +.I unp +is translated. The parameter +.I choices +is a pointer to an array of +.B xdr_discrim(\|) +structures. +Each structure contains an ordered pair of +.RI [ value , proc ]. +If the union's discriminant is equal to the associated +.IR value , +then the +.I proc +is called to translate the union. The end of the +.B xdr_discrim(\|) +structure array is denoted by a routine of value +.SM NULL\s0. +If the discriminant is not found in the +.I choices +array, then the +.I defaultarm +procedure is called (if it is not +.SM NULL\s0). +Returns one if it succeeds, zero otherwise. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +xdr_vector(xdrs, arrp, size, elsize, elproc) +\s-1XDR\s0 *xdrs; +char *arrp; +u_int size, elsize; +xdrproc_t elproc; +.fi +.ft R +.IP +A filter primitive that translates between fixed-length +arrays +and their corresponding external representations. The +parameter +.I arrp +is the address of the pointer to the array, while +.I size +is the element count of the array. The parameter +.I elsize +is the +.I sizeof +each of the array's elements, and +.I elproc +is an +.SM XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 5 +.LP +.ft B +.nf +.sp .5 +xdr_void(\|) +.fi +.ft R +.IP +This routine always returns one. +It may be passed to +.SM RPC +routines that require a function parameter, +where nothing is to be done. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +xdr_wrapstring(xdrs, sp) +\s-1XDR\s0 *xdrs; +char **sp; +.fi +.ft R +.IP +A primitive that calls +.B "xdr_string(xdrs, sp,\s-1MAXUN.UNSIGNED\s0 );" +where +.B +.SM MAXUN.UNSIGNED +is the maximum value of an unsigned integer. +.B xdr_wrapstring(\|) +is handy because the +.SM RPC +package passes a maximum of two +.SM XDR +routines as parameters, and +.BR xdr_string(\|) , +one of the most frequently used primitives, requires three. +Returns one if it succeeds, zero otherwise. +.SH SEE ALSO +.BR rpc (3) +.LP +The following manuals: +.RS +.ft I +eXternal Data Representation Standard: Protocol Specification +.br +eXternal Data Representation: Sun Technical Notes +.ft R +.br +.IR "\s-1XDR\s0: External Data Representation Standard" , +.SM RFC1014, Sun Microsystems, Inc., +.SM USC-ISI\s0. diff --git a/c/src/exec/librpc/src/xdr/xdr.c b/c/src/exec/librpc/src/xdr/xdr.c index e69de29bb2..e608e46501 100644 --- a/c/src/exec/librpc/src/xdr/xdr.c +++ b/c/src/exec/librpc/src/xdr/xdr.c @@ -0,0 +1,777 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/ +/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9 1999/08/28 00:02:55 peter Exp $"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include +#include +#include + +#include +#include + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static 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(proc, objp) + xdrproc_t proc; + char *objp; +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(/* xdrs, addr */) + /* XDR *xdrs; */ + /* caddr_t addr; */ +{ + + return (TRUE); +} + + +/* + * XDR integers + */ +bool_t +xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *ip; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *ip = (int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int(xdrs, up) + XDR *xdrs; + u_int *up; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *up; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *up = (u_int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + return (XDR_PUTLONG(xdrs, lp)); + case XDR_DECODE: + return (XDR_GETLONG(xdrs, lp)); + case XDR_FREE: + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long(xdrs, ulp) + register XDR *xdrs; + u_long *ulp; +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + return (XDR_PUTLONG(xdrs, (long *)ulp)); + case XDR_DECODE: + return (XDR_GETLONG(xdrs, (long *)ulp)); + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR 32-bit integers + * same as xdr_u_int32_t - open coded to save a proc call! + */ +bool_t +xdr_int32_t(xdrs, int32_p) + register XDR *xdrs; + int32_t *int32_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int32_p; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *int32_p = (int32_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned 32-bit integers + * same as xdr_int32_t - open coded to save a proc call! + */ +bool_t +xdr_u_int32_t(xdrs, u_int32_p) + register XDR *xdrs; + u_int32_t *u_int32_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int32_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int32_p = (u_int32_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR 64-bit integers + */ +bool_t +xdr_int64_t(xdrs, int64_p) + register XDR *xdrs; + int64_t *int64_p; +{ + int64_t x; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + return (xdr_opaque(xdrs, (caddr_t)int64_p, sizeof(int64_t))); + + case XDR_DECODE: + if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) { + return (FALSE); + } + *int64_p = x; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned 64-bit integers + */ +bool_t +xdr_u_int64_t(xdrs, uint64_p) + register XDR *xdrs; + u_int64_t *uint64_p; +{ + u_int64_t x; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + return (xdr_opaque(xdrs, (caddr_t)uint64_p, sizeof(u_int64_t))); + + case XDR_DECODE: + if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) { + return (FALSE); + } + *uint64_p = x; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR short integers + */ +bool_t +xdr_short(xdrs, sp) + register XDR *xdrs; + short *sp; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *sp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *sp = (short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short(xdrs, usp) + register XDR *xdrs; + u_short *usp; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR 16-bit integers + */ +bool_t +xdr_int16_t(xdrs, int16_p) + register XDR *xdrs; + int16_t *int16_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int16_p; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *int16_p = (int16_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned 16-bit integers + */ +bool_t +xdr_u_int16_t(xdrs, u_int16_p) + register XDR *xdrs; + u_int16_t *u_int16_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int16_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int16_p = (u_int16_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + int i; + + i = (*cp); + if (!xdr_int(xdrs, &i)) { + return (FALSE); + } + *cp = i; + return (TRUE); +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char(xdrs, cp) + XDR *xdrs; + u_char *cp; +{ + u_int u; + + u = (*cp); + if (!xdr_u_int(xdrs, &u)) { + return (FALSE); + } + *cp = u; + return (TRUE); +} + +/* + * XDR booleans + */ +bool_t +xdr_bool(xdrs, bp) + register XDR *xdrs; + bool_t *bp; +{ + long lb; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return (XDR_PUTLONG(xdrs, &lb)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &lb)) { + return (FALSE); + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +{ +#ifndef lint + enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ep)); + } else if (sizeof (enum sizecheck) == sizeof (int)) { + return (xdr_int(xdrs, (int *)ep)); + } else if (sizeof (enum sizecheck) == sizeof (short)) { + return (xdr_short(xdrs, (short *)ep)); + } else { + return (FALSE); + } +#else + (void) (xdr_short(xdrs, (short *)ep)); + (void) (xdr_int(xdrs, (int *)ep)); + return (xdr_long(xdrs, (long *)ep)); +#endif +} + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque(xdrs, cp, cnt) + register XDR *xdrs; + caddr_t cp; + register u_int cnt; +{ + register u_int rndup; + static int crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return (TRUE); + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + if (xdrs->x_op == XDR_DECODE) { + if (!XDR_GETBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup)); + } + + if (xdrs->x_op == XDR_ENCODE) { + if (!XDR_PUTBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); + } + + if (xdrs->x_op == XDR_FREE) { + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes(xdrs, cpp, sizep, maxsize) + register XDR *xdrs; + char **cpp; + register u_int *sizep; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + register u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) { + *cpp = sp = (char *)mem_alloc(nodesize); + } + if (sp == NULL) { + (void) fprintf(stderr, "xdr_bytes: out of memory\n"); + return (FALSE); + } + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj(xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); +} + +/* + * XDR a descriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union(xdrs, dscmp, unp, choices, dfault) + register XDR *xdrs; + enum_t *dscmp; /* enum to decide which arm to work on */ + char *unp; /* the union itself */ + struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + xdrproc_t dfault; /* default xdr routine */ +{ + register enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (! xdr_enum(xdrs, dscmp)) { + return (FALSE); + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) { + if (choices->value == dscm) + return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault)(xdrs, unp, LASTUNSIGNED)); +} + + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string(xdrs, cpp, maxsize) + register XDR *xdrs; + char **cpp; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) { + case XDR_FREE: + if (sp == NULL) { + return(TRUE); /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + size = strlen(sp); + break; + case XDR_DECODE: /* to avoid warning */ + break; + } + if (! xdr_u_int(xdrs, &size)) { + return (FALSE); + } + if (size > maxsize) { + return (FALSE); + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) + *cpp = sp = (char *)mem_alloc(nodesize); + if (sp == NULL) { + (void) fprintf(stderr, "xdr_string: out of memory\n"); + return (FALSE); + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + return xdr_string(xdrs, cpp, LASTUNSIGNED); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_array.c b/c/src/exec/librpc/src/xdr/xdr_array.c index e69de29bb2..6e4cf96c38 100644 --- a/c/src/exec/librpc/src/xdr/xdr_array.c +++ b/c/src/exec/librpc/src/xdr/xdr_array.c @@ -0,0 +1,157 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_array.c,v 1.8 1999/08/28 00:02:55 peter Exp $"; +#endif + +/* + * xdr_array.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + +#include +#include +#include +#include +#include + +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) + register XDR *xdrs; + caddr_t *addrp; /* array pointer */ + u_int *sizep; /* number of elements */ + u_int maxsize; /* max numberof elements */ + u_int elsize; /* size in bytes of each element */ + xdrproc_t elproc; /* xdr routine to handle each element */ +{ + register u_int i; + register caddr_t target = *addrp; + register u_int c; /* the actual element count */ + register bool_t stat = TRUE; + register u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + c = *sizep; + if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) { + case XDR_DECODE: + if (c == 0) + return (TRUE); + *addrp = target = mem_alloc(nodesize); + if (target == NULL) { + (void) fprintf(stderr, + "xdr_array: out of memory\n"); + return (FALSE); + } + memset(target, 0, nodesize); + break; + + case XDR_FREE: + return (TRUE); + case XDR_ENCODE: /* to avoid warning */ + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) { + stat = (*elproc)(xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) { + mem_free(*addrp, nodesize); + *addrp = NULL; + } + return (stat); +} + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) + register XDR *xdrs; + register char *basep; + register u_int nelem; + register u_int elemsize; + register xdrproc_t xdr_elem; +{ + register u_int i; + register char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) { + if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { + return(FALSE); + } + elptr += elemsize; + } + return(TRUE); +} + diff --git a/c/src/exec/librpc/src/xdr/xdr_float.c b/c/src/exec/librpc/src/xdr/xdr_float.c index e69de29bb2..692fa40366 100644 --- a/c/src/exec/librpc/src/xdr/xdr_float.c +++ b/c/src/exec/librpc/src/xdr/xdr_float.c @@ -0,0 +1,331 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_float.c,v 1.7 1999/08/28 00:02:55 peter Exp $"; +#endif + +/* + * xdr_float.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "floating point" xdr routines used to (de)serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include +#include +#include +#include +#include + +/* + * NB: Not portable. + * This routine works on machines with IEEE754 FP and Vaxen. + */ + +#if defined(__alpha__) || \ + defined(__arm32__) || \ + defined(__hppa__) || \ + defined(__i386__) || \ + defined(__i960__) || \ + defined(__m68k__) || defined(__mc68000__) || \ + defined(__mips__) || \ + defined(__ns32k__) || \ + defined(__sparc__) || \ + defined(__ppc__) || defined(__PPC__) || \ + defined(__sh__) + +#include +#if !defined(IEEEFP) +#define IEEEFP +#endif + +#elif defined(_TMS320C3x) || defined(_TMS320C4x) +#error "Texas Instruments C3x/C4x Not supported." + +#elif defined(vax) + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int mantissa: 23; + unsigned int exp : 8; + unsigned int sign : 1; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} sgl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x0, 0xff, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; +/* end of vax */ +#else +#error "xdr_float.c: unknown CPU" +#endif + + +bool_t +xdr_float(xdrs, fp) + register XDR *xdrs; + register float *fp; +{ +#ifdef IEEEFP + bool_t rv; + long tmpl; +#else + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef IEEEFP + tmpl = *(int32_t *)fp; + return (XDR_PUTLONG(xdrs, &tmpl)); +#else + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTLONG(xdrs, (long *)&is)); +#endif + + case XDR_DECODE: +#ifdef IEEEFP + rv = XDR_GETLONG(xdrs, &tmpl); + *(int32_t *)fp = tmpl; + return (rv); +#else + vsp = (struct vax_single *)fp; + if (!XDR_GETLONG(xdrs, (long *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +#ifdef vax +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int mantissa1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mantissa2 : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; + +#endif /* vax */ + + +bool_t +xdr_double(xdrs, dp) + register XDR *xdrs; + double *dp; +{ +#ifdef IEEEFP + register int32_t *i32p; + bool_t rv; + long tmpl; +#else + register long *lp; + struct ieee_double id; + struct vax_double vd; + register struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef IEEEFP + i32p = (int32_t *)dp; +#if BYTE_ORDER == BIG_ENDIAN + tmpl = *i32p++; + rv = XDR_PUTLONG(xdrs, &tmpl); + if (!rv) + return (rv); + tmpl = *i32p; + rv = XDR_PUTLONG(xdrs, &tmpl); +#else + tmpl = *(i32p+1); + rv = XDR_PUTLONG(xdrs, &tmpl); + if (!rv) + return (rv); + tmpl = *i32p; + rv = XDR_PUTLONG(xdrs, &tmpl); +#endif + return (rv); +#else + vd = *((struct vax_double *)dp); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((vd.mantissa4 == lim->d.mantissa4) && + (vd.mantissa3 == lim->d.mantissa3) && + (vd.mantissa2 == lim->d.mantissa2) && + (vd.mantissa1 == lim->d.mantissa1) && + (vd.exp == lim->d.exp)) { + id = lim->ieee; + goto shipit; + } + } + id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); + id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | + (vd.mantissa3 << 13) | + ((vd.mantissa4 >> 3) & MASK(13)); + shipit: + id.sign = vd.sign; + lp = (long *)&id; + return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); +#endif + + case XDR_DECODE: +#ifdef IEEEFP + i32p = (int32_t *)dp; +#if BYTE_ORDER == BIG_ENDIAN + rv = XDR_GETLONG(xdrs, &tmpl); + *i32p++ = tmpl; + if (!rv) + return (rv); + rv = XDR_GETLONG(xdrs, &tmpl); + *i32p = tmpl; +#else + rv = XDR_GETLONG(xdrs, &tmpl); + *(i32p+1) = tmpl; + if (!rv) + return (rv); + rv = XDR_GETLONG(xdrs, &tmpl); + *i32p = tmpl; +#endif + return (rv); +#else + lp = (long *)&id; + if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_mem.c b/c/src/exec/librpc/src/xdr/xdr_mem.c index e69de29bb2..0b17afa115 100644 --- a/c/src/exec/librpc/src/xdr/xdr_mem.c +++ b/c/src/exec/librpc/src/xdr/xdr_mem.c @@ -0,0 +1,242 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $"; +#endif + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + +#include +#include +#include +#include + +static bool_t xdrmem_getlong_aligned(); +static bool_t xdrmem_putlong_aligned(); +static bool_t xdrmem_getlong_unaligned(); +static bool_t xdrmem_putlong_unaligned(); +static bool_t xdrmem_getbytes(); +static bool_t xdrmem_putbytes(); +static u_int xdrmem_getpos(); /* XXX w/64-bit pointers, u_int not enough! */ +static bool_t xdrmem_setpos(); +static int32_t *xdrmem_inline_aligned(); +static int32_t *xdrmem_inline_unaligned(); +static void xdrmem_destroy(); + +static struct xdr_ops xdrmem_ops_aligned = { + xdrmem_getlong_aligned, + xdrmem_putlong_aligned, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline_aligned, + xdrmem_destroy +}; + +static struct xdr_ops xdrmem_ops_unaligned = { + xdrmem_getlong_unaligned, + xdrmem_putlong_unaligned, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline_unaligned, + xdrmem_destroy +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create(xdrs, addr, size, op) + register XDR *xdrs; + caddr_t 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_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} + +static void +xdrmem_destroy(/*xdrs*/) + /*XDR *xdrs;*/ +{ + +} + +static bool_t +xdrmem_getlong_aligned(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(int32_t)) < 0) + return (FALSE); + *lp = ntohl(*(int32_t *)(xdrs->x_private)); + xdrs->x_private += sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_aligned(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(int32_t)) < 0) + return (FALSE); + *(int32_t *)xdrs->x_private = htonl(*lp); + xdrs->x_private += sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_getlong_unaligned(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + int32_t l; + + if ((xdrs->x_handy -= sizeof(int32_t)) < 0) + return (FALSE); + memcpy(&l, xdrs->x_private, sizeof(int32_t)); + *lp = ntohl(l); + xdrs->x_private += sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_unaligned(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + int32_t l; + + if ((xdrs->x_handy -= sizeof(int32_t)) < 0) + return (FALSE); + l = htonl(*lp); + memcpy(xdrs->x_private, &l, sizeof(int32_t)); + xdrs->x_private += sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_getbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + memcpy(addr, xdrs->x_private, len); + xdrs->x_private += len; + return (TRUE); +} + +static bool_t +xdrmem_putbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + memcpy(xdrs->x_private, addr, len); + xdrs->x_private += len; + return (TRUE); +} + +static u_int +xdrmem_getpos(xdrs) + register XDR *xdrs; +{ + + /* XXX w/64-bit pointers, u_int not enough! */ + return ((u_long)xdrs->x_private - (u_long)xdrs->x_base); +} + +static bool_t +xdrmem_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register caddr_t newaddr = xdrs->x_base + pos; + register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long)newaddr > (long)lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (long)lastaddr - (long)newaddr; + return (TRUE); +} + +static int32_t * +xdrmem_inline_aligned(xdrs, len) + register XDR *xdrs; + 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; + } + return (buf); +} + +static int32_t * +xdrmem_inline_unaligned(xdrs, len) + register XDR *xdrs; + int len; +{ + + return (0); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_rec.c b/c/src/exec/librpc/src/xdr/xdr_rec.c index e69de29bb2..d87b413ee6 100644 --- a/c/src/exec/librpc/src/xdr/xdr_rec.c +++ b/c/src/exec/librpc/src/xdr/xdr_rec.c @@ -0,0 +1,601 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_rec.c,v 1.12 2000/01/19 06:12:32 wpaul Exp $"; +#endif + +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). Thegh order bit encodes + * whether or not the fragment is the last fragment of the record + * (1 => fragment is last, 0 => more fragments to follow. + * The other 31 bits encode the byte length of the fragment. + */ + +#include +#include +#include +#include +#include +#include +#include /* for lseek() */ + +static u_int fix_buf_size(); +static bool_t flush_out(); +static bool_t get_input_bytes(); +static bool_t set_input_fragment(); +static bool_t skip_input_bytes(); + +static bool_t xdrrec_getlong(); +static bool_t xdrrec_putlong(); +static bool_t xdrrec_getbytes(); +static bool_t xdrrec_putbytes(); +static u_int xdrrec_getpos(); +static bool_t xdrrec_setpos(); +static int32_t *xdrrec_inline(); +static void xdrrec_destroy(); + +static struct xdr_ops xdrrec_ops = { + 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 + * 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: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG ((u_int32_t)(1 << 31)) + +typedef struct rec_strm { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-goung bits + */ + int (*writeit) __P((caddr_t, caddr_t, int)); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of current fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit) __P((caddr_t, caddr_t, 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 */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; +} RECSTREAM; + + +/* + * Create an xdr handle for xdrrec + * xdrrec_create fills in xdrs. Sendsize and recvsize are + * send and recv buffer sizes (0 => use default). + * tcp_handle is an opaque handle that is passed as the first parameter to + * the procedures readit and writeit. Readit and writeit are read and + * write respectively. They are like the system + * calls expect that they take an opaque handle rather than an fd. + */ +void +xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) + register XDR *xdrs; + register u_int sendsize; + register u_int recvsize; + caddr_t tcp_handle; + int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ + int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ +{ + register RECSTREAM *rstrm = + (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); + + if (rstrm == NULL) { + (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + /* + * 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->recvsize = recvsize = fix_buf_size(recvsize); + rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); + if (rstrm->the_buffer == NULL) { + (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + 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; + 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->out_finger += sizeof(u_int32_t); + rstrm->out_boundry += sendsize; + rstrm->frag_sent = FALSE; + rstrm->in_size = recvsize; + rstrm->in_boundry = rstrm->in_base; + rstrm->in_finger = (rstrm->in_boundry += recvsize); + rstrm->fbtbc = 0; + rstrm->last_frag = TRUE; +} + + +/* + * The reoutines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register int32_t *buflp = (int32_t *)(rstrm->in_finger); + int32_t mylong; + + /* first try the inline, fast case */ + if ((rstrm->fbtbc >= sizeof(int32_t)) && + (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { + *lp = (long)ntohl((u_int32_t)(*buflp)); + rstrm->fbtbc -= sizeof(int32_t); + rstrm->in_finger += sizeof(int32_t); + } else { + if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(int32_t))) + return (FALSE); + *lp = (long)ntohl((u_int32_t)mylong); + } + return (TRUE); +} + +static bool_t +xdrrec_putlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register int32_t *dest_lp = ((int32_t *)(rstrm->out_finger)); + + if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= sizeof(int32_t); + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + dest_lp = ((int32_t *)(rstrm->out_finger)); + rstrm->out_finger += sizeof(int32_t); + } + *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); + return (TRUE); +} + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes(xdrs, addr, len) + XDR *xdrs; + register caddr_t addr; + register u_int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register int current; + + while (len > 0) { + current = rstrm->fbtbc; + if (current == 0) { + if (rstrm->last_frag) + return (FALSE); + if (! set_input_fragment(rstrm)) + return (FALSE); + continue; + } + current = (len < current) ? len : current; + if (! get_input_bytes(rstrm, addr, current)) + return (FALSE); + addr += current; + rstrm->fbtbc -= current; + len -= current; + } + return (TRUE); +} + +static bool_t +xdrrec_putbytes(xdrs, addr, len) + XDR *xdrs; + register caddr_t addr; + register u_int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register long current; + + while (len > 0) { + current = (u_long)rstrm->out_boundry - + (u_long)rstrm->out_finger; + current = (len < current) ? len : current; + memcpy(rstrm->out_finger, addr, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry) { + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + } + } + return (TRUE); +} + +static u_int +xdrrec_getpos(xdrs) + register XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + register long pos; + + pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1); + if (pos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = -1; + break; + } + return ((u_int) pos); +} + +static bool_t +xdrrec_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + u_int currpos = xdrrec_getpos(xdrs); + int delta = currpos - pos; + caddr_t newpos; + + if ((int)currpos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if ((newpos > (caddr_t)(rstrm->frag_header)) && + (newpos < rstrm->out_boundry)) { + rstrm->out_finger = newpos; + return (TRUE); + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int)(rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return (TRUE); + } + break; + case XDR_FREE: /* to avoid warning */ + break; + } + return (FALSE); +} + +static int32_t * +xdrrec_inline(xdrs, len) + register XDR *xdrs; + int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + int32_t * buf = NULL; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) { + buf = (int32_t *) rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) { + buf = (int32_t *) rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + case XDR_FREE: /* to avoid warning */ + break; + } + return (buf); +} + +static void +xdrrec_destroy(xdrs) + register XDR *xdrs; +{ + register 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)); +} + + +/* + * Exported routines to manage xdr records + */ + +/* + * Before reading (deserializing from the stream, one should always call + * this procedure to guarantee proper record alignment. + */ +bool_t +xdrrec_skiprecord(xdrs) + XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (FALSE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (FALSE); + } + rstrm->last_frag = FALSE; + return (TRUE); +} + +/* + * Look ahead fuction. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +bool_t +xdrrec_eof(xdrs) + XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (TRUE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (TRUE); + } + if (rstrm->in_finger == rstrm->in_boundry) + return (TRUE); + return (FALSE); +} + +/* + * The client must tell the package when an end-of-record has occurred. + * The second paraemters tells whether the record should be flushed to the + * (output) tcp stream. (This let's the package support batched or + * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. + */ +bool_t +xdrrec_endofrecord(xdrs, sendnow) + XDR *xdrs; + bool_t sendnow; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent || + ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= + (u_long)rstrm->out_boundry)) { + rstrm->frag_sent = FALSE; + return (flush_out(rstrm, TRUE)); + } + 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->out_finger += sizeof(u_int32_t); + return (TRUE); +} + + +/* + * Internal useful routines + */ +static bool_t +flush_out(rstrm, eor) + register RECSTREAM *rstrm; + bool_t eor; +{ + register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; + register u_int32_t len = (u_long)(rstrm->out_finger) - + (u_long)(rstrm->frag_header) - sizeof(u_int32_t); + + *(rstrm->frag_header) = htonl(len | eormask); + len = (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); + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf(rstrm) + register RECSTREAM *rstrm; +{ + register caddr_t where; + u_long i; + register long len; + + where = rstrm->in_base; + i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT; + where += i; + len = rstrm->in_size - i; + if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) + return (FALSE); + rstrm->in_finger = where; + where += len; + rstrm->in_boundry = where; + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +get_input_bytes(rstrm, addr, len) + register RECSTREAM *rstrm; + register caddr_t addr; + register int len; +{ + register long current; + + while (len > 0) { + current = (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); + rstrm->in_finger += current; + addr += current; + len -= current; + } + return (TRUE); +} + +static bool_t /* next two bytes of the input stream are treated as a header */ +set_input_fragment(rstrm) + register RECSTREAM *rstrm; +{ + u_int32_t header; + + if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) + return (FALSE); + header = (long)ntohl(header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect + * record sizes. Unfortunately, the only record size + * we can positively identify as being 'wildly incorrect' + * is zero. Ridiculously large record sizes may look wrong, + * but we don't have any way to be certain that they aren't + * what the client actually intended to send us. + */ + if (header == 0) + return(FALSE); + rstrm->fbtbc = header & (~LAST_FRAG); + return (TRUE); +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +skip_input_bytes(rstrm, cnt) + register RECSTREAM *rstrm; + long cnt; +{ + register long current; + + while (cnt > 0) { + current = (long)rstrm->in_boundry - (long)rstrm->in_finger; + if (current == 0) { + if (! fill_input_buf(rstrm)) + return (FALSE); + continue; + } + current = (cnt < current) ? cnt : current; + rstrm->in_finger += current; + cnt -= current; + } + return (TRUE); +} + +static u_int +fix_buf_size(s) + register u_int s; +{ + + if (s < 100) + s = 4000; + return (RNDUP(s)); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_reference.c b/c/src/exec/librpc/src/xdr/xdr_reference.c index e69de29bb2..41ac34b220 100644 --- a/c/src/exec/librpc/src/xdr/xdr_reference.c +++ b/c/src/exec/librpc/src/xdr/xdr_reference.c @@ -0,0 +1,138 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/ +/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.8 1999/08/28 00:02:56 peter Exp $"; +#endif + +/* + * xdr_reference.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1987, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * "pointers". See xdr.h for more info on the interface to xdr. + */ + +#include +#include +#include +#include +#include + +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the sizeof the referneced structure. + * proc is the routine to handle the referenced structure. + */ +bool_t +xdr_reference(xdrs, pp, size, proc) + register XDR *xdrs; + caddr_t *pp; /* the pointer to work on */ + u_int size; /* size of the object pointed to */ + xdrproc_t proc; /* xdr routine to handle the object */ +{ + register caddr_t loc = *pp; + register bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) { + case XDR_FREE: + return (TRUE); + + case XDR_DECODE: + *pp = loc = (caddr_t) mem_alloc(size); + if (loc == NULL) { + (void) fprintf(stderr, + "xdr_reference: out of memory\n"); + return (FALSE); + } + memset(loc, 0, (int)size); + break; + case XDR_ENCODE: /* to avoid warning */ + break; + } + + stat = (*proc)(xdrs, loc, LASTUNSIGNED); + + if (xdrs->x_op == XDR_FREE) { + mem_free(loc, size); + *pp = NULL; + } + return (stat); +} + + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialiaze + * trees correctly. + * + * What's sent is actually a union: + * + * union object_pointer switch (boolean b) { + * case TRUE: object_data data; + * case FALSE: void nothing; + * } + * + * > objpp: Pointer to the pointer to the object. + * > obj_size: size of the object. + * > xdr_obj: routine to XDR an object. + * + */ +bool_t +xdr_pointer(xdrs,objpp,obj_size,xdr_obj) + register XDR *xdrs; + char **objpp; + u_int obj_size; + xdrproc_t xdr_obj; +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (! xdr_bool(xdrs,&more_data)) { + return (FALSE); + } + if (! more_data) { + *objpp = NULL; + return (TRUE); + } + return (xdr_reference(xdrs,objpp,obj_size,xdr_obj)); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_sizeof.c b/c/src/exec/librpc/src/xdr/xdr_sizeof.c index e69de29bb2..5a4c1a78dc 100644 --- a/c/src/exec/librpc/src/xdr/xdr_sizeof.c +++ b/c/src/exec/librpc/src/xdr/xdr_sizeof.c @@ -0,0 +1,163 @@ +/* + * 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 + */ +/* + * xdr_sizeof.c + * + * Copyright 1990 Sun Microsystems, Inc. + * + * General purpose routine to see how much space something will use + * when serialized using XDR. + */ + +#include +#include +#include +#include + +/* ARGSUSED */ +static bool_t +x_putlong(xdrs, longp) + XDR *xdrs; + long *longp; +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return (TRUE); +} + +/* ARGSUSED */ +static bool_t +x_putbytes(xdrs, bp, len) + XDR *xdrs; + char *bp; + int len; +{ + xdrs->x_handy += len; + return (TRUE); +} + +static u_int +x_getpostn(xdrs) + XDR *xdrs; +{ + return (xdrs->x_handy); +} + +/* ARGSUSED */ +static bool_t +x_setpostn(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + /* This is not allowed */ + return (FALSE); +} + +static int32_t * +x_inline(xdrs, len) + XDR *xdrs; + long len; +{ + if (len == 0) { + return (NULL); + } + if (xdrs->x_op != XDR_ENCODE) { + return (NULL); + } + if (len < (long) xdrs->x_base) { + /* x_private was already allocated */ + xdrs->x_handy += len; + return ((int32_t *) xdrs->x_private); + } else { + /* Free the earlier space and allocate new area */ + if (xdrs->x_private) + free(xdrs->x_private); + if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) { + xdrs->x_base = 0; + return (NULL); + } + xdrs->x_base = (caddr_t) len; + xdrs->x_handy += len; + return ((int32_t *) xdrs->x_private); + } +} + +static int +harmless() +{ + /* Always return FALSE/NULL, as the case may be */ + return (0); +} + +static void +x_destroy(xdrs) + XDR *xdrs; +{ + xdrs->x_handy = 0; + xdrs->x_base = 0; + if (xdrs->x_private) { + free(xdrs->x_private); + xdrs->x_private = NULL; + } + return; +} + +unsigned long +xdr_sizeof(func, data) + xdrproc_t func; + void *data; +{ + XDR x; + struct xdr_ops ops; + bool_t stat; + /* to stop ANSI-C compiler from complaining */ + typedef bool_t (* dummyfunc1)(XDR *, long *); + typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int); + + ops.x_putlong = x_putlong; + ops.x_putbytes = x_putbytes; + ops.x_inline = x_inline; + ops.x_getpostn = x_getpostn; + ops.x_setpostn = x_setpostn; + ops.x_destroy = x_destroy; + + /* the other harmless ones */ + ops.x_getlong = (dummyfunc1) harmless; + ops.x_getbytes = (dummyfunc2) harmless; + + x.x_op = XDR_ENCODE; + x.x_ops = &ops; + x.x_handy = 0; + x.x_private = (caddr_t) NULL; + x.x_base = (caddr_t) 0; + + stat = func(&x, data); + if (x.x_private) + free(x.x_private); + return (stat == TRUE ? (unsigned) x.x_handy: 0); +} diff --git a/c/src/exec/librpc/src/xdr/xdr_stdio.c b/c/src/exec/librpc/src/xdr/xdr_stdio.c index e69de29bb2..9db1b12e9e 100644 --- a/c/src/exec/librpc/src/xdr/xdr_stdio.c +++ b/c/src/exec/librpc/src/xdr/xdr_stdio.c @@ -0,0 +1,189 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/ +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_stdio.c,v 1.7 1999/08/28 00:02:56 peter Exp $"; +#endif + +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements a XDR on a stdio stream. + * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes + * from the stream. + */ + +#include +#include +#include + +static bool_t xdrstdio_getlong(); +static bool_t xdrstdio_putlong(); +static bool_t xdrstdio_getbytes(); +static bool_t xdrstdio_putbytes(); +static u_int xdrstdio_getpos(); +static bool_t xdrstdio_setpos(); +static int32_t *xdrstdio_inline(); +static void xdrstdio_destroy(); + +/* + * Ops vector for stdio type XDR + */ +static struct xdr_ops xdrstdio_ops = { + xdrstdio_getlong, /* deseraialize a long int */ + xdrstdio_putlong, /* seraialize a long int */ + xdrstdio_getbytes, /* deserialize counted bytes */ + xdrstdio_putbytes, /* serialize counted bytes */ + xdrstdio_getpos, /* get offset in the stream */ + xdrstdio_setpos, /* set offset in the stream */ + xdrstdio_inline, /* prime stream for inline macros */ + xdrstdio_destroy /* destroy stream */ +}; + +/* + * Initialize a stdio xdr stream. + * Sets the xdr stream handle xdrs for use on the stream file. + * Operation flag is set to op. + */ +void +xdrstdio_create(xdrs, file, op) + register 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_handy = 0; + xdrs->x_base = 0; +} + +/* + * Destroy a stdio xdr stream. + * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. + */ +static void +xdrstdio_destroy(xdrs) + register XDR *xdrs; +{ + (void)fflush((FILE *)xdrs->x_private); + /* xx should we close the file ?? */ +} + +static bool_t +xdrstdio_getlong(xdrs, lp) + XDR *xdrs; + register long *lp; +{ + + if (fread((caddr_t)lp, sizeof(int32_t), 1, + (FILE *)xdrs->x_private) != 1) + return (FALSE); + *lp = (long)ntohl((int32_t)*lp); + return (TRUE); +} + +static bool_t +xdrstdio_putlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + + long mycopy = (long)htonl((int32_t)*lp); + + if (fwrite((caddr_t)&mycopy, sizeof(int32_t), 1, + (FILE *)xdrs->x_private) != 1) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_getbytes(xdrs, addr, len) + XDR *xdrs; + caddr_t addr; + u_int len; +{ + + if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_putbytes(xdrs, addr, len) + XDR *xdrs; + caddr_t addr; + u_int len; +{ + + if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static u_int +xdrstdio_getpos(xdrs) + XDR *xdrs; +{ + + return ((u_int) ftell((FILE *)xdrs->x_private)); +} + +static bool_t +xdrstdio_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + + return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ? + FALSE : TRUE); +} + +static int32_t * +xdrstdio_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return (NULL); +} diff --git a/c/src/exec/posix/include/Makefile.am b/c/src/exec/posix/include/Makefile.am index 4abe5df1ee..387e599641 100644 --- a/c/src/exec/posix/include/Makefile.am +++ b/c/src/exec/posix/include/Makefile.am @@ -7,22 +7,21 @@ AUTOMAKE_OPTIONS = foreign 1.4 ## RTEMS unistd.h needs to be checked against newlib's and removed UNUSED_H_FILES = devctl.h intr.h unistd.h -H_FILES = pthread.h sched.h aio.h mqueue.h semaphore.h +H_FILES = sched.h aio.h mqueue.h semaphore.h + +# H_FILES = pthread.h sched.h aio.h mqueue.h semaphore.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) $(PROJECT_INCLUDE): @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) SUBDIRS = rtems sys diff --git a/c/src/exec/posix/include/pthread.h b/c/src/exec/posix/include/pthread.h deleted file mode 100644 index 8141a53548..0000000000 --- a/c/src/exec/posix/include/pthread.h +++ /dev/null @@ -1,509 +0,0 @@ -/* pthread.h - * - * $Id$ - */ - -#ifndef __PTHREAD_h -#define __PTHREAD_h - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#if defined(_POSIX_THREADS) - -#include -#include -#include - -/* - * 3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27 - * - * RTEMS does not support processes, so we fall under this and do not - * provide this routine: - * - * "Either the implementation shall support the pthread_atfork() function - * as described above or the pthread_atfork() funciton shall not be - * provided." - */ - -/* - * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 - */ - -int pthread_mutexattr_init( - pthread_mutexattr_t *attr -); - -int pthread_mutexattr_destroy( - pthread_mutexattr_t *attr -); - -int pthread_mutexattr_getpshared( - const pthread_mutexattr_t *attr, - int *pshared -); - -int pthread_mutexattr_setpshared( - pthread_mutexattr_t *attr, - int pshared -); - -/* - * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 - */ - -int pthread_mutex_init( - pthread_mutex_t *mutex, - const pthread_mutexattr_t *attr -); - -int pthread_mutex_destroy( - pthread_mutex_t *mutex -); - -/* - * This is used to statically initialize a pthread_mutex_t. Example: - * - * pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - */ - -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF) - -/* - * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 - * - * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 - */ - -int pthread_mutex_lock( - pthread_mutex_t *mutex -); - -int pthread_mutex_trylock( - pthread_mutex_t *mutex -); - -int pthread_mutex_unlock( - pthread_mutex_t *mutex -); - -#if defined(_POSIX_TIMEOUTS) - -int pthread_mutex_timedlock( - pthread_mutex_t *mutex, - const struct timespec *timeout -); - -#endif /* _POSIX_TIMEOUTS */ - -/* - * 11.4.1 Condition Variable Initialization Attributes, - * P1003.1c/Draft 10, p. 96 - */ - -int pthread_condattr_init( - pthread_condattr_t *attr -); - -int pthread_condattr_destroy( - pthread_condattr_t *attr -); - -int pthread_condattr_getpshared( - const pthread_condattr_t *attr, - int *pshared -); - -int pthread_condattr_setpshared( - pthread_condattr_t *attr, - int pshared -); - -/* - * 11.4.2 Initializing and Destroying a Condition Variable, - * P1003.1c/Draft 10, p. 87 - */ - -int pthread_cond_init( - pthread_cond_t *cond, - const pthread_condattr_t *attr -); - -int pthread_cond_destroy( - pthread_cond_t *mutex -); - -/* - * This is used to statically initialize a pthread_cond_t. Example: - * - * pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - */ - -#define PTHREAD_COND_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF) - -/* - * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 - */ - -int pthread_cond_signal( - pthread_cond_t *cond -); - -int pthread_cond_broadcast( - pthread_cond_t *cond -); - -/* - * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 - */ - -int pthread_cond_wait( - pthread_cond_t *cond, - pthread_mutex_t *mutex -); - -int pthread_cond_timedwait( - pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime -); - -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - -/* - * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 - */ - -int pthread_attr_setscope( - pthread_attr_t *attr, - int contentionscope -); - -int pthread_attr_getscope( - const pthread_attr_t *attr, - int *contentionscope -); - -int pthread_attr_setinheritsched( - pthread_attr_t *attr, - int inheritsched -); - -int pthread_attr_getinheritsched( - const pthread_attr_t *attr, - int *inheritsched -); - -int pthread_attr_setschedpolicy( - pthread_attr_t *attr, - int policy -); - -int pthread_attr_getschedpolicy( - const pthread_attr_t *attr, - int *policy -); - -#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ - -int pthread_attr_setschedparam( - pthread_attr_t *attr, - const struct sched_param *param -); - -int pthread_attr_getschedparam( - const pthread_attr_t *attr, - struct sched_param *param -); - -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - -/* - * 13.5.2 Dynamic Thread Scheduling Parameters Access, - * P1003.1c/Draft 10, p. 124 - */ - -int pthread_getschedparam( - pthread_t thread, - int *policy, - struct sched_param *param -); - -int pthread_setschedparam( - pthread_t thread, - int policy, - struct sched_param *param -); - -#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ - -#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) - -/* - * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 - */ - -int pthread_mutexattr_setprotocol( - pthread_mutexattr_t *attr, - int protocol -); - -int pthread_mutexattr_getprotocol( - const pthread_mutexattr_t *attr, - int *protocol -); - -int pthread_mutexattr_setprioceiling( - pthread_mutexattr_t *attr, - int prioceiling -); - -int pthread_mutexattr_getprioceiling( - const pthread_mutexattr_t *attr, - int *prioceiling -); - -#endif /* _POSIX_THREAD_PRIO_INHERIT || _POSIX_THREAD_PRIO_PROTECT */ - -#if defined(_POSIX_THREAD_PRIO_PROTECT) - -/* - * 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131 - */ - -int pthread_mutex_setprioceiling( - pthread_mutex_t *mutex, - int prioceiling, - int *old_ceiling -); - -int pthread_mutex_getprioceiling( - pthread_mutex_t *mutex, - int *prioceiling -); - -#endif /* _POSIX_THREAD_PRIO_PROTECT */ - -/* - * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 - */ - -int pthread_attr_init( - pthread_attr_t *attr -); - -int pthread_attr_destroy( - pthread_attr_t *attr -); - -int pthread_attr_getstacksize( - const pthread_attr_t *attr, - size_t *stacksize -); - -int pthread_attr_setstacksize( - pthread_attr_t *attr, - size_t stacksize -); - -int pthread_attr_getstackaddr( - const pthread_attr_t *attr, - void **stackaddr -); - -int pthread_attr_setstackaddr( - pthread_attr_t *attr, - void *stackaddr -); - -int pthread_attr_getdetachstate( - const pthread_attr_t *attr, - int *detachstate -); - -int pthread_attr_setdetachstate( - pthread_attr_t *attr, - int detachstate -); - -/* - * 16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144 - */ - -int pthread_create( - pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine)( void * ), - void *arg -); - -/* - * 16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147 - */ - -int pthread_join( - pthread_t thread, - void **value_ptr -); - -/* - * 16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149 - */ - -int pthread_detach( - pthread_t thread -); - -/* - * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150 - */ - -void pthread_exit( - void *value_ptr -); - -/* - * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX - */ - -pthread_t pthread_self( void ); - -/* - * 16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153 - */ - -int pthread_equal( - pthread_t t1, - pthread_t t2 -); - -/* - * 16.1.8 Dynamic Package Initialization - */ - -/* - * This is used to statically initialize a pthread_once_t. Example: - * - * pthread_once_t once = PTHREAD_ONCE_INIT; - * - * NOTE: This is named inconsistently -- it should be INITIALIZER. - */ - -#define PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */ - -int pthread_once( - pthread_once_t *once_control, - void (*init_routine)(void) -); - -/* - * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 - */ - -int pthread_key_create( - pthread_key_t *key, - void (*destructor)( void * ) -); - -/* - * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 - */ - -int pthread_setspecific( - pthread_key_t key, - const void *value -); - -void *pthread_getspecific( - pthread_key_t key -); - -/* - * 17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167 - */ - -int pthread_key_delete( - pthread_key_t key -); - -/* - * 18.2.1 Canceling Execution of a Thread, P1003.1c/Draft 10, p. 181 - */ - -#define PTHREAD_CANCEL_ENABLE 0 -#define PTHREAD_CANCEL_DISABLE 1 - -#define PTHREAD_CANCEL_DEFERRED 0 -#define PTHREAD_CANCEL_ASYNCHRONOUS 1 - -int pthread_cancel( - pthread_t thread -); - -/* - * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 - */ - -int pthread_setcancelstate( - int state, - int *oldstate -); - -int pthread_setcanceltype( - int type, - int *oldtype -); - -void pthread_testcancel( void ); - -/* - * 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184 - */ - -void pthread_cleanup_push( - void (*routine)( void * ), - void *arg -); - -void pthread_cleanup_pop( - int execute -); - -#if defined(_POSIX_THREAD_CPUTIME) - -/* - * 20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58 - */ - -int pthread_getcpuclockid( - pthread_t thread_id, - clockid_t *clock_id -); - -/* - * 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59 - */ - -int pthread_attr_setcputime( - pthread_attr_t *attr, - int clock_allowed -); - -int pthread_attr_getcputime( - pthread_attr_t *attr, - int *clock_allowed -); - -#endif /* defined(_POSIX_THREAD_CPUTIME) */ - -#endif /* defined(_POSIX_THREADS) */ - -#ifdef __cplusplus -} -#endif - -#endif -/* end of include file */ diff --git a/c/src/exec/posix/include/rtems/posix/Makefile.am b/c/src/exec/posix/include/rtems/posix/Makefile.am index 96b9bad59b..c66a0015c9 100644 --- a/c/src/exec/posix/include/rtems/posix/Makefile.am +++ b/c/src/exec/posix/include/rtems/posix/Makefile.am @@ -10,7 +10,7 @@ STD_H_FILES = cancel.h cond.h config.h key.h mqueue.h mutex.h posixapi.h \ priority.h psignal.h pthread.h ptimer.h semaphore.h seterr.h threadsup.h \ time.h timer.h $(MP_H_FILES) -UNUSED_H_FILES= intr.h threadsup.h +UNUSED_H_FILES = intr.h threadsup.h if HAS_MP H_FILES = $(STD_H_FILES) $(MP_H_FILES) @@ -20,18 +20,15 @@ endif noinst_HEADERS = $(STD_H_FILES) $(MP_H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/posix \ -$(H_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix \ + $(H_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) $(PROJECT_INCLUDE)/rtems/posix: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/rtems/posix/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) EXTRA_DIST = $(UNUSED_H_FILES) diff --git a/c/src/exec/posix/include/sys/Makefile.am b/c/src/exec/posix/include/sys/Makefile.am index 2ac2975304..f07a7218b3 100644 --- a/c/src/exec/posix/include/sys/Makefile.am +++ b/c/src/exec/posix/include/sys/Makefile.am @@ -8,17 +8,14 @@ H_FILES = utsname.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/sys \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/sys/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/sys/%) $(PROJECT_INCLUDE)/sys: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/sys/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/exec/posix/inline/rtems/posix/Makefile.am b/c/src/exec/posix/inline/rtems/posix/Makefile.am index 89b3c87d3b..a38f1fa8f1 100644 --- a/c/src/exec/posix/inline/rtems/posix/Makefile.am +++ b/c/src/exec/posix/inline/rtems/posix/Makefile.am @@ -3,16 +3,16 @@ ## AUTOMAKE_OPTIONS = foreign 1.4 + #I_FILES= intr.inl I_FILES = cond.inl key.inl mqueue.inl mutex.inl pthread.inl priority.inl \ - semaphore.inl + semaphore.inl noinst_HEADERS = $(I_FILES) if INLINE -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/posix \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) $(PROJECT_INCLUDE)/rtems/posix: @$(mkinstalldirs) $@ @@ -20,9 +20,7 @@ $(PROJECT_INCLUDE)/rtems/posix/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) EXTRA_DIST = intr.inl diff --git a/c/src/exec/posix/inline/rtems/posix/cond.inl b/c/src/exec/posix/inline/rtems/posix/cond.inl index d718ef514f..19d5c6ec4b 100644 --- a/c/src/exec/posix/inline/rtems/posix/cond.inl +++ b/c/src/exec/posix/inline/rtems/posix/cond.inl @@ -53,10 +53,13 @@ RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control *_POSIX_Condition_variabl Objects_Locations *location ) { -/* XXX really should validate pointer */ /* XXX should support COND_INITIALIZER */ - return (POSIX_Condition_variables_Control *) - _Objects_Get( &_POSIX_Condition_variables_Information, *id, location ); + if ( id ) + return (POSIX_Condition_variables_Control *) + _Objects_Get( &_POSIX_Condition_variables_Information, *id, location ); + + *location = OBJECTS_ERROR; + return NULL; } /*PAGE diff --git a/c/src/exec/posix/macros/rtems/posix/Makefile.am b/c/src/exec/posix/macros/rtems/posix/Makefile.am index 32f810b57c..48f00c8a30 100644 --- a/c/src/exec/posix/macros/rtems/posix/Makefile.am +++ b/c/src/exec/posix/macros/rtems/posix/Makefile.am @@ -9,9 +9,8 @@ I_FILES = noinst_HEADERS = $(I_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/posix \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/posix/%) $(PROJECT_INCLUDE)/rtems/posix: @$(mkinstalldirs) $@ @@ -19,8 +18,6 @@ $(PROJECT_INCLUDE)/rtems/posix/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/exec/posix/optman/Makefile.am b/c/src/exec/posix/optman/Makefile.am index bf02adffdd..c6277ca054 100644 --- a/c/src/exec/posix/optman/Makefile.am +++ b/c/src/exec/posix/optman/Makefile.am @@ -13,7 +13,7 @@ include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../../automake/lib.am TMPINSTALL_FILES += \ -$(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) + $(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel $(INSTALL_DATA) $< $@ @@ -22,7 +22,6 @@ $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel # (OPTIONAL) Add local stuff here using += # -AM_CFLAGS += $(CFLAGS_OS_V) ASM4FLAGS += -I$(PROJECT_INCLUDE)/rtems all-local: ${ARCH} $(PGMS) $(TMPINSTALL_FILES) diff --git a/c/src/exec/posix/src/Makefile.am b/c/src/exec/posix/src/Makefile.am index 63fd5adc0f..506d9c53fa 100644 --- a/c/src/exec/posix/src/Makefile.am +++ b/c/src/exec/posix/src/Makefile.am @@ -91,12 +91,11 @@ include $(top_srcdir)/../../../../automake/lib.am # AM_CPPFLAGS += -D__RTEMS_INSIDE__ -AM_CFLAGS += $(CFLAGS_OS_V) -all: ${ARCH} ${OBJS} +all-local: ${ARCH} ${OBJS} # temporary so we can see how many things are left to implement -not: +not: grep -i NOT_IMPL $(C_FILES) | grep -v MP_NOT_IMPL @echo @echo diff --git a/c/src/exec/posix/src/mqueuecreatesupp.c b/c/src/exec/posix/src/mqueuecreatesupp.c index 148f5b54cb..6b3e5dbe58 100644 --- a/c/src/exec/posix/src/mqueuecreatesupp.c +++ b/c/src/exec/posix/src/mqueuecreatesupp.c @@ -74,7 +74,7 @@ int _POSIX_Message_queue_Create_support( attr = *attr_ptr; } -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED && !( _Objects_MP_Allocate_and_open( &_POSIX_Message_queue_Information, 0, the_mq->Object.id, FALSE ) ) ) { @@ -112,14 +112,14 @@ int _POSIX_Message_queue_Create_support( the_mq_attr, attr.mq_maxmsg, attr.mq_msgsize, -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) _POSIX_Message_queue_MP_Send_extract_proxy #else NULL #endif ) ) { -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED ) _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq->Object.id ); #endif @@ -137,7 +137,7 @@ int _POSIX_Message_queue_Create_support( *message_queue = the_mq; -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED ) _POSIX_Message_queue_MP_Send_process_packet( POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE, diff --git a/c/src/exec/posix/src/mqueuedeletesupp.c b/c/src/exec/posix/src/mqueuedeletesupp.c index ec717aedad..f8076d601a 100644 --- a/c/src/exec/posix/src/mqueuedeletesupp.c +++ b/c/src/exec/posix/src/mqueuedeletesupp.c @@ -48,7 +48,7 @@ void _POSIX_Message_queue_Delete( _POSIX_Message_queue_Free( the_mq ); -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) { _Objects_MP_Close( diff --git a/c/src/exec/posix/src/mqueueunlink.c b/c/src/exec/posix/src/mqueueunlink.c index 4c219eecea..26399386a7 100644 --- a/c/src/exec/posix/src/mqueueunlink.c +++ b/c/src/exec/posix/src/mqueueunlink.c @@ -63,7 +63,7 @@ int mq_unlink( _Objects_Get_index( the_mq_id ) ); -#if defined(RTEMS_MULTIPROCESSING) +#if 0 && defined(RTEMS_MULTIPROCESSING) if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) { _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq_id ); } diff --git a/c/src/exec/posix/src/pthread.c b/c/src/exec/posix/src/pthread.c index 49f6273a71..46a41a1da5 100644 --- a/c/src/exec/posix/src/pthread.c +++ b/c/src/exec/posix/src/pthread.c @@ -356,8 +356,8 @@ void _POSIX_Threads_Manager_initialization( FALSE, /* does not support global */ maximum_pthreads, sizeof( Thread_Control ), - TRUE, - 5, /* length is arbitrary for now */ + FALSE, + 0, /* length is arbitrary for now */ TRUE /* this class is threads */ ); diff --git a/c/src/exec/posix/src/pthreadcreate.c b/c/src/exec/posix/src/pthreadcreate.c index b4e4788f2e..c936e6ec65 100644 --- a/c/src/exec/posix/src/pthreadcreate.c +++ b/c/src/exec/posix/src/pthreadcreate.c @@ -34,7 +34,6 @@ int pthread_create( boolean is_fp; boolean status; Thread_Control *the_thread; - char *default_name = "psx"; POSIX_API_Control *api; int schedpolicy = SCHED_RR; struct sched_param schedparam; @@ -177,7 +176,7 @@ int pthread_create( budget_algorithm, budget_callout, 0, /* isr level */ - &default_name /* posix threads don't have a name */ + NULL /* posix threads don't have a name */ ); if ( !status ) { diff --git a/c/src/exec/posix/src/sigtimedwait.c b/c/src/exec/posix/src/sigtimedwait.c index b3b2de247d..276b9b61af 100644 --- a/c/src/exec/posix/src/sigtimedwait.c +++ b/c/src/exec/posix/src/sigtimedwait.c @@ -21,6 +21,7 @@ #include #include #include +#include int _POSIX_signals_Get_highest( sigset_t set @@ -55,7 +56,27 @@ int sigtimedwait( siginfo_t signal_information; siginfo_t *the_info; int signo; + ISR_Level level; + /* + * Error check parameters before disabling interrupts. + */ + + interval = 0; + if ( timeout ) { + + if ( timeout->tv_nsec < 0 || + timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) { + set_errno_and_return_minus_one( EINVAL ); + } + + interval = _POSIX_Timespec_to_interval( timeout ); + } + + /* + * Initialize local variables. + */ + the_info = ( info ) ? info : &signal_information; the_thread = _Thread_Executing; @@ -68,11 +89,13 @@ int sigtimedwait( /* API signals pending? */ + _ISR_Disable( level ); if ( *set & api->signals_pending ) { /* XXX real info later */ the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending ); - _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, - FALSE, FALSE ); + _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, FALSE, FALSE ); + _ISR_Enable( level ); + the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; return the_info->si_signo; @@ -83,6 +106,7 @@ int sigtimedwait( if ( *set & _POSIX_signals_Pending ) { signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending ); _POSIX_signals_Clear_signals( api, signo, the_info, TRUE, FALSE ); + _ISR_Enable( level ); the_info->si_signo = signo; the_info->si_code = SI_USER; @@ -90,15 +114,6 @@ int sigtimedwait( return signo; } - interval = 0; - if ( timeout ) { - - if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) - set_errno_and_return_minus_one( EINVAL ); - - interval = _POSIX_Timespec_to_interval( timeout ); - } - the_info->si_signo = -1; _Thread_Disable_dispatch(); @@ -107,6 +122,7 @@ int sigtimedwait( the_thread->Wait.option = *set; the_thread->Wait.return_argument = (void *) the_info; _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); + _ISR_Enable( level ); _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); _Thread_Enable_dispatch(); @@ -115,9 +131,7 @@ int sigtimedwait( * the signal. */ - _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, - FALSE, FALSE ); - + _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, FALSE, FALSE ); errno = _Thread_Executing->Wait.return_code; return the_info->si_signo; } diff --git a/c/src/exec/posix/src/waitpid.c b/c/src/exec/posix/src/waitpid.c index f20161b5a9..d52177961d 100644 --- a/c/src/exec/posix/src/waitpid.c +++ b/c/src/exec/posix/src/waitpid.c @@ -8,8 +8,10 @@ #include #include -int wait( - int *stat_loc +int waitpid( + pid_t pid, + int *stat_loc, + int options ) { errno = ENOSYS; diff --git a/c/src/exec/rtems/include/Makefile.am b/c/src/exec/rtems/include/Makefile.am index 8935b30100..09e318db3b 100644 --- a/c/src/exec/rtems/include/Makefile.am +++ b/c/src/exec/rtems/include/Makefile.am @@ -8,18 +8,15 @@ H_FILES = rtems.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) $(PROJECT_INCLUDE): @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) SUBDIRS = rtems diff --git a/c/src/exec/rtems/include/rtems/rtems/Makefile.am b/c/src/exec/rtems/include/rtems/rtems/Makefile.am index b27c67a0e5..f9c8d82fef 100644 --- a/c/src/exec/rtems/include/rtems/rtems/Makefile.am +++ b/c/src/exec/rtems/include/rtems/rtems/Makefile.am @@ -5,12 +5,12 @@ AUTOMAKE_OPTIONS = foreign 1.4 ## We only build multiprocessing related files if HAS_MP was defined -MP_H_FILES = eventmp.h mp.h msgmp.h partmp.h regionmp.h semmp.h \ - signalmp.h taskmp.h +MP_H_FILES = eventmp.h mp.h msgmp.h partmp.h regionmp.h semmp.h signalmp.h \ + taskmp.h -STD_H_FILES = asr.h attr.h clock.h config.h dpmem.h event.h eventset.h intr.h \ - message.h modes.h options.h part.h ratemon.h region.h rtemsapi.h sem.h \ - signal.h status.h support.h tasks.h timer.h types.h +STD_H_FILES = asr.h attr.h clock.h config.h dpmem.h event.h eventset.h \ + intr.h message.h modes.h options.h part.h ratemon.h region.h rtemsapi.h \ + sem.h signal.h status.h support.h tasks.h timer.h types.h if HAS_MP H_FILES = $(STD_H_FILES) $(MP_H_FILES) @@ -20,17 +20,14 @@ endif noinst_HEADERS = $(STD_H_FILES) $(MP_H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/rtems \ -$(H_FILES:%=$(PROJECT_INCLUDE)/rtems/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems \ + $(H_FILES:%=$(PROJECT_INCLUDE)/rtems/rtems/%) $(PROJECT_INCLUDE)/rtems/rtems: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/rtems/rtems/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/rtems/include/rtems/rtems/rtemsapi.h b/c/src/exec/rtems/include/rtems/rtems/rtemsapi.h index 6b1cfd8d05..0028cf3980 100644 --- a/c/src/exec/rtems/include/rtems/rtems/rtemsapi.h +++ b/c/src/exec/rtems/include/rtems/rtems/rtemsapi.h @@ -22,7 +22,9 @@ * * _RTEMS_API_Initialize * - * XXX + * This routine initializes the RTEMS API by invoking the initialization + * routine for each RTEMS manager with the appropriate parameters + * from the configuration_table. */ void _RTEMS_API_Initialize( diff --git a/c/src/exec/rtems/inline/rtems/rtems/Makefile.am b/c/src/exec/rtems/inline/rtems/rtems/Makefile.am index 44dde4db1b..b8b787a40e 100644 --- a/c/src/exec/rtems/inline/rtems/rtems/Makefile.am +++ b/c/src/exec/rtems/inline/rtems/rtems/Makefile.am @@ -6,14 +6,13 @@ AUTOMAKE_OPTIONS = foreign 1.4 if INLINE I_FILES = asr.inl attr.inl dpmem.inl event.inl eventset.inl message.inl \ - modes.inl options.inl part.inl ratemon.inl \ - region.inl sem.inl status.inl support.inl tasks.inl timer.inl + modes.inl options.inl part.inl ratemon.inl region.inl sem.inl status.inl \ + support.inl tasks.inl timer.inl noinst_HEADERS = $(I_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/rtems \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/rtems/%) $(PROJECT_INCLUDE)/rtems/rtems: @$(mkinstalldirs) $@ @@ -21,8 +20,6 @@ $(PROJECT_INCLUDE)/rtems/rtems/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/rtems/macros/rtems/rtems/Makefile.am b/c/src/exec/rtems/macros/rtems/rtems/Makefile.am index 65e0594cfd..dacf3011fe 100644 --- a/c/src/exec/rtems/macros/rtems/rtems/Makefile.am +++ b/c/src/exec/rtems/macros/rtems/rtems/Makefile.am @@ -5,16 +5,15 @@ AUTOMAKE_OPTIONS = foreign 1.4 I_FILES = asr.inl attr.inl dpmem.inl event.inl eventset.inl message.inl \ - modes.inl options.inl part.inl ratemon.inl \ - region.inl sem.inl status.inl support.inl tasks.inl timer.inl + modes.inl options.inl part.inl ratemon.inl region.inl sem.inl status.inl \ + support.inl tasks.inl timer.inl noinst_HEADERS = $(I_FILES) if MACROS -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/rtems \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/rtems/%) $(PROJECT_INCLUDE)/rtems/rtems: @$(mkinstalldirs) $@ @@ -22,8 +21,6 @@ $(PROJECT_INCLUDE)/rtems/rtems/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/rtems/optman/Makefile.am b/c/src/exec/rtems/optman/Makefile.am index 943e9cb210..dc6c6292b7 100644 --- a/c/src/exec/rtems/optman/Makefile.am +++ b/c/src/exec/rtems/optman/Makefile.am @@ -14,7 +14,7 @@ include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../automake/lib.am TMPINSTALL_FILES += \ -$(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) + $(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel $(INSTALL_DATA) $< $@ @@ -23,7 +23,6 @@ $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel # (OPTIONAL) Add local stuff here using += # -AM_CFLAGS += $(CFLAGS_OS_V) ASM4FLAGS += -I$(PROJECT_INCLUDE)/rtems all-local: ${ARCH} $(PGMS) $(TMPINSTALL_FILES) diff --git a/c/src/exec/rtems/optman/no-mp.c b/c/src/exec/rtems/optman/no-mp.c index 5fc8f81df6..6c23d4e923 100644 --- a/c/src/exec/rtems/optman/no-mp.c +++ b/c/src/exec/rtems/optman/no-mp.c @@ -156,6 +156,7 @@ Thread _MPCI_Receive_server( FALSE, RTEMS_NOT_CONFIGURED ); + return NULL; } void _MPCI_Announce ( void ) diff --git a/c/src/exec/rtems/src/Makefile.am b/c/src/exec/rtems/src/Makefile.am index 16d932dc9d..f597292be1 100644 --- a/c/src/exec/rtems/src/Makefile.am +++ b/c/src/exec/rtems/src/Makefile.am @@ -42,7 +42,7 @@ SIGNAL_C_FILES = signal.c signalcatch.c signalsend.c REGION_C_FILES = region.c regioncreate.c regiondelete.c regionextend.c \ regiongetsegment.c regiongetsegmentsize.c regionident.c \ - regionreturnsegment.c regionreturnsegment.c + regionreturnsegment.c PARTITION_C_FILES = part.c partcreate.c partdelete.c partgetbuffer.c \ partident.c partreturnbuffer.c @@ -70,9 +70,8 @@ OBJS = $(C_O_FILES) # AM_CPPFLAGS += -D__RTEMS_INSIDE__ -AM_CFLAGS += $(CFLAGS_OS_V) -all: ${ARCH} ${OBJS} +all-local: ${ARCH} ${OBJS} EXTRA_DIST = $(STD_C_FILES) $(MP_C_FILES) diff --git a/c/src/exec/rtems/src/semdelete.c b/c/src/exec/rtems/src/semdelete.c index 1e9b165c71..079d9ed810 100644 --- a/c/src/exec/rtems/src/semdelete.c +++ b/c/src/exec/rtems/src/semdelete.c @@ -61,6 +61,12 @@ * error code - if unsuccessful */ +#if defined(RTEMS_MULTIPROCESSING) +#define SEMAPHORE_MP_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted +#else +#define SEMAPHORE_MP_OBJECT_WAS_DELETED NULL +#endif + rtems_status_code rtems_semaphore_delete( Objects_Id id ) @@ -81,32 +87,25 @@ rtems_status_code rtems_semaphore_delete( return RTEMS_INVALID_ID; case OBJECTS_LOCAL: - if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { - if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) ) { + if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) && + !_Attributes_Is_simple_binary_semaphore( + the_semaphore->attribute_set ) ) { _Thread_Enable_dispatch(); return RTEMS_RESOURCE_IN_USE; } - else - _CORE_mutex_Flush( - &the_semaphore->Core_control.mutex, -#if defined(RTEMS_MULTIPROCESSING) - _Semaphore_MP_Send_object_was_deleted, -#else - NULL, -#endif - CORE_MUTEX_WAS_DELETED - ); - } - else + _CORE_mutex_Flush( + &the_semaphore->Core_control.mutex, + SEMAPHORE_MP_OBJECT_WAS_DELETED, + CORE_MUTEX_WAS_DELETED + ); + } else { _CORE_semaphore_Flush( &the_semaphore->Core_control.semaphore, -#if defined(RTEMS_MULTIPROCESSING) - _Semaphore_MP_Send_object_was_deleted, -#else - NULL, -#endif + SEMAPHORE_MP_OBJECT_WAS_DELETED, CORE_SEMAPHORE_WAS_DELETED ); + } _Objects_Close( &_Semaphore_Information, &the_semaphore->Object ); diff --git a/c/src/exec/rtems/src/tasks.c b/c/src/exec/rtems/src/tasks.c index 5fdff2db18..40426642c9 100644 --- a/c/src/exec/rtems/src/tasks.c +++ b/c/src/exec/rtems/src/tasks.c @@ -105,6 +105,8 @@ User_extensions_routine _RTEMS_tasks_Delete_extension( next = tvp->next; if (tvp->dtor) (*tvp->dtor)( tvp->ptr ); + if (executing == deleted) + *tvp->ptr = tvp->gval; _Workspace_Free( tvp ); tvp = next; } @@ -137,13 +139,15 @@ void _RTEMS_tasks_Switch_extension( tvp = executing->task_variables; while (tvp) { - tvp->var = *tvp->ptr; + tvp->tval = *tvp->ptr; + *tvp->ptr = tvp->gval; tvp = tvp->next; } tvp = heir->task_variables; while (tvp) { - *tvp->ptr = tvp->var; + tvp->gval = *tvp->ptr; + *tvp->ptr = tvp->tval; tvp = tvp->next; } } diff --git a/c/src/exec/rtems/src/taskvariableadd.c b/c/src/exec/rtems/src/taskvariableadd.c index 0f1ae0895e..04d56d409d 100644 --- a/c/src/exec/rtems/src/taskvariableadd.c +++ b/c/src/exec/rtems/src/taskvariableadd.c @@ -72,7 +72,7 @@ rtems_status_code rtems_task_variable_add( _Thread_Enable_dispatch(); return RTEMS_NO_MEMORY; } - new->var = 0; + new->gval = *ptr; new->ptr = ptr; new->dtor = dtor; diff --git a/c/src/exec/rtems/src/taskvariabledelete.c b/c/src/exec/rtems/src/taskvariabledelete.c index c760f9ba39..d87a772c18 100644 --- a/c/src/exec/rtems/src/taskvariabledelete.c +++ b/c/src/exec/rtems/src/taskvariabledelete.c @@ -53,6 +53,8 @@ rtems_status_code rtems_task_variable_delete( if (tvp->ptr == ptr) { if (prev) prev->next = tvp->next; else the_thread->task_variables = tvp->next; + if (_Thread_Is_executing (the_thread)) + *tvp->ptr = tvp->gval; _Thread_Enable_dispatch(); _Workspace_Free(tvp); return RTEMS_SUCCESSFUL; diff --git a/c/src/exec/rtems/src/taskvariableget.c b/c/src/exec/rtems/src/taskvariableget.c index 9beb0c4045..cc6e98045c 100644 --- a/c/src/exec/rtems/src/taskvariableget.c +++ b/c/src/exec/rtems/src/taskvariableget.c @@ -59,7 +59,7 @@ rtems_status_code rtems_task_variable_get( * Should this return the current (i.e not the * saved) value if `tid' is the current task? */ - *result = tvp->var; + *result = tvp->tval; _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; } diff --git a/c/src/exec/sapi/include/Makefile.am b/c/src/exec/sapi/include/Makefile.am index 5391ab5d89..d206ebc214 100644 --- a/c/src/exec/sapi/include/Makefile.am +++ b/c/src/exec/sapi/include/Makefile.am @@ -8,18 +8,15 @@ H_FILES = confdefs.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/%) $(PROJECT_INCLUDE): @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) SUBDIRS = rtems diff --git a/c/src/exec/sapi/include/confdefs.h b/c/src/exec/sapi/include/confdefs.h index 8e2e876aad..16b51cdc1f 100644 --- a/c/src/exec/sapi/include/confdefs.h +++ b/c/src/exec/sapi/include/confdefs.h @@ -1,9 +1,27 @@ /* confdefs.h * * This include file contains the configuration table template that will - * be used by the single processor tests to define its default configuration - * parameters. + * be instantiated by an application based on the setting of a number + * of macros. The macros are documented in the Configuring a System + * chapter of the Classic API User's Guide * + * The model is to estimate the memory required for each configured item + * and sum those estimates. The estimate can be too high or too low for + * a variety of reasons: + * + * Reasons estimate is too high: + * + FP contexts (not all tasks are FP) + * + * Reasons estimate is too low: + * + stacks greater than minimum size + * + messages + * + application must account for device driver resources + * + application must account for add-on library resource requirements + * + * NOTE: Eventually this may be able to take into account some of + * the above. This procedure has evolved from just enough to + * support the RTEMS Test Suites into something that can be + * used remarkably reliably by most applications. * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * @@ -41,8 +59,12 @@ extern itron_api_configuration_table Configuration_ITRON_API; #define CONFIGURE_NEWLIB_EXTENSION 1 #define CONFIGURE_MALLOC_REGION 1 +/* + * File descriptors managed by libio + */ + #ifndef CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS -#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20 +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 3 #endif #define CONFIGURE_LIBIO_SEMAPHORES \ @@ -52,6 +74,22 @@ extern itron_api_configuration_table Configuration_ITRON_API; unsigned32 rtems_libio_number_iops = CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS; #endif +/* + * Termios resources + */ + +#ifdef CONFIGURE_TERMIOS_DISABLED +#define CONFIGURE_TERMIOS_SEMAPHORES 0 +#else + +#ifndef CONFIGURE_NUMBER_OF_TERMIOS_PORTS +#define CONFIGURE_NUMBER_OF_TERMIOS_PORTS 1 +#endif + +#define CONFIGURE_TERMIOS_SEMAPHORES \ + ((CONFIGURE_NUMBER_OF_TERMIOS_PORTS * 4) + 1) +#endif + /* * Mount Table Configuration */ @@ -62,10 +100,10 @@ unsigned32 rtems_libio_number_iops = CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS; #ifndef CONFIGURE_HAS_OWN_MOUNT_TABLE rtems_filesystem_mount_table_t configuration_mount_table = { -#ifdef CONFIGURE_USE_MINIIMFS_AS_BASE_FILESYSTEM - &miniIMFS_ops, -#else /* using IMFS as base filesystem */ +#ifdef CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM &IMFS_ops, +#else /* using miniIMFS as base filesystem */ + &miniIMFS_ops, #endif RTEMS_FILESYSTEM_READ_WRITE, NULL, @@ -94,15 +132,17 @@ int rtems_filesystem_mount_table_size = 1; /* * Interrupt Stack Space + * + * NOTE: There is currently no way for the application to override + * the interrupt stack size set by the BSP. */ #if (CPU_ALLOCATE_INTERRUPT_STACK == 0) +#undef CONFIGURE_INTERRUPT_STACK_MEMORY #define CONFIGURE_INTERRUPT_STACK_MEMORY 0 #else #ifndef CONFIGURE_INTERRUPT_STACK_MEMORY #define CONFIGURE_INTERRUPT_STACK_MEMORY RTEMS_MINIMUM_STACK_SIZE - #else - #define CONFIGURE_INTERRUPT_STACK_MEMORY 0 #endif #endif @@ -177,6 +217,29 @@ rtems_initialization_tasks_table Initialization_tasks[] = { #endif +/* + * Map obsolete names to current ones + * + * NOTE: These should be obsoleted in a future release. + */ + +#ifdef CONFIGURE_TEST_NEEDS_TIMER_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER +#endif +#ifdef CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#endif +#ifdef CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#endif +#ifdef CONFIGURE_TEST_NEEDS_RTC_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER +#endif +#ifdef CONFIGURE_TEST_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#endif + + /* * Default Device Driver Table. Each driver needed by the test is explicitly * choosen by that test. There is always a null driver entry. @@ -185,11 +248,19 @@ rtems_initialization_tasks_table Initialization_tasks[] = { #define NULL_DRIVER_TABLE_ENTRY \ { NULL, NULL, NULL, NULL, NULL, NULL } -#ifdef CONFIGURE_TEST_NEEDS_TIMER_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#include +#endif + +#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#include +#endif + +#ifdef CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #include #endif -#ifdef CONFIGURE_TEST_NEEDS_STUB_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER #include #endif @@ -197,13 +268,13 @@ rtems_initialization_tasks_table Initialization_tasks[] = { #ifdef CONFIGURE_INIT rtems_driver_address_table Device_drivers[] = { -#ifdef CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER CONSOLE_DRIVER_TABLE_ENTRY, #endif -#ifdef CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER CLOCK_DRIVER_TABLE_ENTRY, #endif -#ifdef CONFIGURE_TEST_NEEDS_STUB_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER STUB_DRIVER_TABLE_ENTRY, #endif NULL_DRIVER_TABLE_ENTRY @@ -217,21 +288,17 @@ rtems_driver_address_table Device_drivers[] = { * overridden by the user. */ -#ifndef CONFIGURE_HAS_OWN_NUMBER_OF_DEVICES - #ifndef CONFIGURE_MAXIMUM_DEVICES #define CONFIGURE_MAXIMUM_DEVICES 20 #endif -#endif /* CONFIGURE_HAS_OWN_NUMBER_OF_DEVICES */ - /* - * Default Configuration Table. This table contains the most values set in - * the RTEMS Test Suite. Each value may be overridden within each test to - * customize the environment. + * Default Multiprocessing Configuration Table. The defaults are + * appropriate for most of the RTEMS Multiprocessor Test Suite. Each + * value may be overridden within each test to customize the environment. */ -#ifdef CONFIGURE_MPTEST +#ifdef CONFIGURE_MP_APPLICATION #ifndef CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE #ifndef CONFIGURE_MP_NODE_NUMBER @@ -273,12 +340,10 @@ rtems_multiprocessing_table Multiprocessing_configuration = { #define CONFIGURE_MULTIPROCESSING_TABLE NULL -#endif /* CONFIGURE_MPTEST */ +#endif /* CONFIGURE_MP_APPLICATION */ /* - * Default Configuration Table. This table contains the most values set in - * the RTEMS Test Suite. Each value may be overridden within each test to - * customize the environment. + * Default Configuration Table. */ #ifndef CONFIGURE_HAS_OWN_CONFIGURATION_TABLE @@ -288,7 +353,7 @@ rtems_multiprocessing_table Multiprocessing_configuration = { #endif #ifndef CONFIGURE_MAXIMUM_TASKS -#define CONFIGURE_MAXIMUM_TASKS 10 +#define CONFIGURE_MAXIMUM_TASKS 0 #endif #ifndef CONFIGURE_MAXIMUM_TIMERS @@ -374,7 +439,7 @@ rtems_extensions_table Configuration_Initial_Extensions[] = { #include #ifndef CONFIGURE_MAXIMUM_POSIX_THREADS -#define CONFIGURE_MAXIMUM_POSIX_THREADS 10 +#define CONFIGURE_MAXIMUM_POSIX_THREADS 0 #endif #ifndef CONFIGURE_MAXIMUM_POSIX_MUTEXES @@ -411,7 +476,7 @@ rtems_extensions_table Configuration_Initial_Extensions[] = { /* * The user is defining their own table information and setting the - * appropriate variables. + * appropriate variables for the POSIX Initialization Thread Table. */ #else @@ -528,7 +593,7 @@ posix_initialization_threads_table POSIX_Initialization_threads[] = { #include #ifndef CONFIGURE_MAXIMUM_ITRON_TASKS -#define CONFIGURE_MAXIMUM_ITRON_TASKS 10 +#define CONFIGURE_MAXIMUM_ITRON_TASKS 0 #endif #ifndef CONFIGURE_MAXIMUM_ITRON_SEMAPHORES @@ -565,7 +630,7 @@ posix_initialization_threads_table POSIX_Initialization_threads[] = { /* * The user is defining their own table information and setting the - * appropriate variables. + * appropriate variables for the ITRON Initialization Task Table. */ #else @@ -690,22 +755,6 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { /* * Calculate the RAM size based on the maximum number of objects configured. - * The model is to estimate the memory required for each configured item, - * sum the memory requirements and insure that there is at least 32K greater - * than that for things not directly addressed such as: - * - * + stacks greater than minimum size - * + FP contexts - * + API areas (should be optional) - * + messages - * + object name and local pointer table overhead - * + per node memory requirements - * + executive fixed requirements (including at least internal threads - * and the Ready chains) - * - * NOTE: Eventually this should take into account some of the above. - * Basically, this is a "back of the envelope" estimate for - * memory requirements. It could be more accurate. */ #ifndef CONFIGURE_EXECUTIVE_RAM_SIZE @@ -756,7 +805,7 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { #define CONFIGURE_MEMORY_FOR_DEVICES(_devices) \ (((_devices) + 1) * ( sizeof(rtems_driver_name_t) ) ) -#ifdef CONFIGURE_MPTEST +#ifdef CONFIGURE_MP_APPLICATION #ifndef CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE @@ -788,7 +837,7 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { #define CONFIGURE_EXTRA_TASK_STACKS 0 #endif -#define CONFIGURE_MEMORY_FOR_SYSTEM_OVEREHAD \ +#define CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD \ ( CONFIGURE_MEMORY_FOR_TASKS(1) + /* IDLE */ \ (256 * 12) + /* Ready chains */ \ 256 + /* name/ptr table overhead */ \ @@ -803,7 +852,7 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { CONFIGURE_MAXIMUM_ITRON_TASKS ) + \ CONFIGURE_MEMORY_FOR_TIMERS(CONFIGURE_MAXIMUM_TIMERS) + \ CONFIGURE_MEMORY_FOR_SEMAPHORES(CONFIGURE_MAXIMUM_SEMAPHORES + \ - CONFIGURE_LIBIO_SEMAPHORES) + \ + CONFIGURE_LIBIO_SEMAPHORES + CONFIGURE_TERMIOS_SEMAPHORES) + \ CONFIGURE_MEMORY_FOR_MESSAGE_QUEUES(CONFIGURE_MAXIMUM_MESSAGE_QUEUES) + \ CONFIGURE_MEMORY_FOR_PARTITIONS(CONFIGURE_MAXIMUM_PARTITIONS) + \ CONFIGURE_MEMORY_FOR_REGIONS( \ @@ -815,7 +864,7 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { CONFIGURE_STACK_CHECKER_EXTENSION ) + \ CONFIGURE_MEMORY_FOR_DEVICES(CONFIGURE_MAXIMUM_DEVICES) + \ CONFIGURE_MEMORY_FOR_MP + \ - CONFIGURE_MEMORY_FOR_SYSTEM_OVEREHAD + \ + CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD + \ (((CONFIGURE_MEMORY_OVERHEAD)+1) * 1024) + \ (CONFIGURE_EXTRA_TASK_STACKS) + (CONFIGURE_ADA_TASKS_STACK) \ ) & 0xfffffc00) @@ -853,7 +902,8 @@ itron_initialization_tasks_table ITRON_Initialization_tasks[] = { rtems_api_configuration_table Configuration_RTEMS_API = { CONFIGURE_MAXIMUM_TASKS, CONFIGURE_MAXIMUM_TIMERS, - CONFIGURE_MAXIMUM_SEMAPHORES + CONFIGURE_LIBIO_SEMAPHORES, + CONFIGURE_MAXIMUM_SEMAPHORES + CONFIGURE_LIBIO_SEMAPHORES + + CONFIGURE_TERMIOS_SEMAPHORES, CONFIGURE_MAXIMUM_MESSAGE_QUEUES, CONFIGURE_MAXIMUM_PARTITIONS, CONFIGURE_MAXIMUM_REGIONS + CONFIGURE_MALLOC_REGION, @@ -929,5 +979,31 @@ rtems_configuration_table Configuration = { } #endif +/* + * Some warnings and error checking + */ + +/* + * Make sure a task/thread of some sort is configured + */ + +#if (CONFIGURE_MAXIMUM_TASKS == 0) && \ + (CONFIGURE_MAXIMUM_POSIX_THREADS == 0) && \ + (CONFIGURE_MAXIMUM_ADA_TASKS == 0) && \ + (CONFIGURE_MAXIMUM_ITRON_TASKS == 0) +#error "CONFIGURATION ERROR: No tasks or threads configured!! +#endif + +/* + * Make sure at least one of the initialization task/thread + * tables was defined. + */ + +#if !defined(CONFIGURE_RTEMS_INIT_TASKS_TABLE) && \ + !defined(CONFIGURE_POSIX_INIT_THREAD_TABLE) && \ + !defined(CONFIGURE_ITRON_INIT_TASK_TABLE) +#error "CONFIGURATION ERROR: No initialization tasks or threads configured!! +#endif + #endif /* end of include file */ diff --git a/c/src/exec/sapi/include/rtems/Makefile.am b/c/src/exec/sapi/include/rtems/Makefile.am index deabd8b0b5..0483ede4c3 100644 --- a/c/src/exec/sapi/include/rtems/Makefile.am +++ b/c/src/exec/sapi/include/rtems/Makefile.am @@ -5,13 +5,12 @@ AUTOMAKE_OPTIONS = foreign 1.4 H_FILES = config.h directives.h extension.h fatal.h init.h io.h mptables.h \ - sptables.h + sptables.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) $(PROJECT_INCLUDE)/rtems: @$(mkinstalldirs) $@ @@ -20,8 +19,6 @@ $(PROJECT_INCLUDE)/rtems/%.h: %.h EXTRA_DIST = README -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/sapi/include/rtems/README b/c/src/exec/sapi/include/rtems/README index 5fcc0d14c7..f29bdb45b7 100644 --- a/c/src/exec/sapi/include/rtems/README +++ b/c/src/exec/sapi/include/rtems/README @@ -24,10 +24,8 @@ the Timing Test Suite: /* configuration information */ - #define CONFIGURE_TMTEST - - #define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER - #define CONFIGURE_TEST_NEEDS_TIMER_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #define CONFIGURE_MAXIMUM_TASKS 102 #define CONFIGURE_MAXIMUM_TIMERS 100 @@ -60,13 +58,13 @@ template by default. { NULL, NULL, NULL, NULL, NULL, NULL } rtems_driver_address_table Device_drivers[] = { -#ifdef CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER CONSOLE_DRIVER_TABLE_ENTRY, #endif -#ifdef CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER CLOCK_DRIVER_TABLE_ENTRY, #endif -#ifdef CONFIGURE_TEST_NEEDS_STUB_DRIVER +#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER STUB_DRIVER_TABLE_ENTRY, #endif NULL_DRIVER_TABLE_ENTRY, @@ -83,7 +81,7 @@ rtems_initialization_tasks_table Initialization_tasks[] = { } }; -#ifdef CONFIGURE_MPTEST +#ifdef CONFIGURE_MP_APPLICATION /* * NODE_NUMBER is assumed to be set on the compile line. */ @@ -127,7 +125,7 @@ rtems_configuration_table Configuration = { /* number of device drivers */ Device_drivers, /* pointer to driver address table */ NULL, /* pointer to initial extensions */ -#ifdef CONFIGURE_MPTEST +#ifdef CONFIGURE_MP_APPLICATION &Multiprocessing_configuration #else NULL /* ptr to MP config table */ diff --git a/c/src/exec/sapi/inline/rtems/Makefile.am b/c/src/exec/sapi/inline/rtems/Makefile.am index 804d5be2f9..cdc59dd96a 100644 --- a/c/src/exec/sapi/inline/rtems/Makefile.am +++ b/c/src/exec/sapi/inline/rtems/Makefile.am @@ -9,9 +9,8 @@ I_FILES = extension.inl noinst_HEADERS = $(I_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) $(PROJECT_INCLUDE)/rtems: @$(mkinstalldirs) $@ @@ -19,8 +18,6 @@ $(PROJECT_INCLUDE)/rtems/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/sapi/macros/rtems/Makefile.am b/c/src/exec/sapi/macros/rtems/Makefile.am index 991f6865b2..857ad0615c 100644 --- a/c/src/exec/sapi/macros/rtems/Makefile.am +++ b/c/src/exec/sapi/macros/rtems/Makefile.am @@ -9,9 +9,8 @@ I_FILES = extension.inl noinst_HEADERS = $(I_FILES) if MACROS -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) $(PROJECT_INCLUDE)/rtems: @$(mkinstalldirs) $@ @@ -19,8 +18,6 @@ $(PROJECT_INCLUDE)/rtems/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/sapi/optman/Makefile.am b/c/src/exec/sapi/optman/Makefile.am index c98b33860f..76d3e4fbb8 100644 --- a/c/src/exec/sapi/optman/Makefile.am +++ b/c/src/exec/sapi/optman/Makefile.am @@ -13,7 +13,7 @@ include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../automake/lib.am TMPINSTALL_FILES += \ -$(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) + $(C_FILES:%.c=$(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel) $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel $(INSTALL_DATA) $< $@ @@ -22,7 +22,6 @@ $(PROJECT_RELEASE)/lib/%$(LIB_VARIANT).rel: $(ARCH)/%.rel # (OPTIONAL) Add local stuff here using += # -AM_CFLAGS += $(CFLAGS_OS_V) ASM4FLAGS += -I $(PROJECT_INCLUDE)/rtems all-local: ${ARCH} $(PGMS) $(TMPINSTALL_FILES) diff --git a/c/src/exec/sapi/src/Makefile.am b/c/src/exec/sapi/src/Makefile.am index 91d461279c..a9d642921d 100644 --- a/c/src/exec/sapi/src/Makefile.am +++ b/c/src/exec/sapi/src/Makefile.am @@ -18,9 +18,8 @@ include $(top_srcdir)/../../../automake/lib.am # AM_CPPFLAGS += -D__RTEMS_INSIDE__ -AM_CFLAGS += $(CFLAGS_OS_V) -all: ${ARCH} ${OBJS} +all-local: ${ARCH} ${OBJS} EXTRA_DIST = $(C_FILES) diff --git a/c/src/exec/score/cpu/a29k/Makefile.am b/c/src/exec/score/cpu/a29k/Makefile.am index a740e396a3..92cdcbd384 100644 --- a/c/src/exec/score/cpu/a29k/Makefile.am +++ b/c/src/exec/score/cpu/a29k/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -41,7 +41,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/a29k/rtems/Makefile.am b/c/src/exec/score/cpu/a29k/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/a29k/rtems/Makefile.am +++ b/c/src/exec/score/cpu/a29k/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/a29k/rtems/score/Makefile.am b/c/src/exec/score/cpu/a29k/rtems/score/Makefile.am index 5ec1ac9f61..6f47d2e20b 100644 --- a/c/src/exec/score/cpu/a29k/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/a29k/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/a29k/rtems/score/a29k.h b/c/src/exec/score/cpu/a29k/rtems/score/a29k.h index 7dd9030609..e1e359d075 100644 --- a/c/src/exec/score/cpu/a29k/rtems/score/a29k.h +++ b/c/src/exec/score/cpu/a29k/rtems/score/a29k.h @@ -28,7 +28,16 @@ extern "C" { * of the family. */ -#if defined(a29205) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define A29K_HAS_FPU 0 + +#elif defined(a29205) #define CPU_MODEL_NAME "a29205" #define A29K_HAS_FPU 0 diff --git a/c/src/exec/score/cpu/hppa1.1/Makefile.am b/c/src/exec/score/cpu/hppa1.1/Makefile.am index 882f9ca597..f26f2ca8fa 100644 --- a/c/src/exec/score/cpu/hppa1.1/Makefile.am +++ b/c/src/exec/score/cpu/hppa1.1/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -36,7 +36,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/hppa1.1/rtems/Makefile.am b/c/src/exec/score/cpu/hppa1.1/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/hppa1.1/rtems/Makefile.am +++ b/c/src/exec/score/cpu/hppa1.1/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/hppa1.1/rtems/score/Makefile.am b/c/src/exec/score/cpu/hppa1.1/rtems/score/Makefile.am index 5fa8d31b1d..f578ebdda9 100644 --- a/c/src/exec/score/cpu/hppa1.1/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/hppa1.1/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/hppa1.1/rtems/score/hppa.h b/c/src/exec/score/cpu/hppa1.1/rtems/score/hppa.h index 049981ea84..1e1e3284df 100644 --- a/c/src/exec/score/cpu/hppa1.1/rtems/score/hppa.h +++ b/c/src/exec/score/cpu/hppa1.1/rtems/score/hppa.h @@ -35,7 +35,15 @@ extern "C" { * present in a particular member of the family. */ -#if defined(hppa7100) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" + +#elif defined(hppa7100) #define CPU_MODEL_NAME "hppa 7100" diff --git a/c/src/exec/score/cpu/i386/Makefile.am b/c/src/exec/score/cpu/i386/Makefile.am index ff1f7dd610..2801a9fc88 100644 --- a/c/src/exec/score/cpu/i386/Makefile.am +++ b/c/src/exec/score/cpu/i386/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/i386/rtems/Makefile.am b/c/src/exec/score/cpu/i386/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/i386/rtems/Makefile.am +++ b/c/src/exec/score/cpu/i386/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/i386/rtems/score/Makefile.am b/c/src/exec/score/cpu/i386/rtems/score/Makefile.am index a3bdd523b1..9d7ca37423 100644 --- a/c/src/exec/score/cpu/i386/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/i386/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/i386/rtems/score/i386.h b/c/src/exec/score/cpu/i386/rtems/score/i386.h index 977670a75b..f113ebee4e 100644 --- a/c/src/exec/score/cpu/i386/rtems/score/i386.h +++ b/c/src/exec/score/cpu/i386/rtems/score/i386.h @@ -46,7 +46,17 @@ extern "C" { * */ -#if defined(i386_fp) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define I386_HAS_FPU 0 +#define I386_HAS_BSWAP 0 + +#elif defined(i386_fp) #define CPU_MODEL_NAME "i386 with i387" #define I386_HAS_BSWAP 0 diff --git a/c/src/exec/score/cpu/i960/Makefile.am b/c/src/exec/score/cpu/i960/Makefile.am index 9e45e1dcd4..f26a4e9382 100644 --- a/c/src/exec/score/cpu/i960/Makefile.am +++ b/c/src/exec/score/cpu/i960/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/i960/rtems/Makefile.am b/c/src/exec/score/cpu/i960/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/i960/rtems/Makefile.am +++ b/c/src/exec/score/cpu/i960/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/i960/rtems/score/Makefile.am b/c/src/exec/score/cpu/i960/rtems/score/Makefile.am index 9614ab9e49..c7c8212303 100644 --- a/c/src/exec/score/cpu/i960/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/i960/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/i960/rtems/score/i960.h b/c/src/exec/score/cpu/i960/rtems/score/i960.h index ae9a073aff..644bd18a0b 100644 --- a/c/src/exec/score/cpu/i960/rtems/score/i960.h +++ b/c/src/exec/score/cpu/i960/rtems/score/i960.h @@ -33,7 +33,18 @@ extern "C" { * NOTE: RTEMS defines a canonical name for each cpu model. */ -#if defined(__i960CA__) || defined(__i960_CA__) || defined(__i960CA) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define I960_HAS_FPU 0 +#define I960_CPU_ALIGNMENT 4 +#define I960_SOFT_RESET_COMMAND 0x30000 + +#elif defined(__i960CA__) || defined(__i960_CA__) || defined(__i960CA) #define CPU_MODEL_NAME "i960ca" #define __RTEMS_I960CA__ diff --git a/c/src/exec/score/cpu/m68k/Makefile.am b/c/src/exec/score/cpu/m68k/Makefile.am index 4ff7a91ff7..cffdcf4fc4 100644 --- a/c/src/exec/score/cpu/m68k/Makefile.am +++ b/c/src/exec/score/cpu/m68k/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/m68k/qsm.h b/c/src/exec/score/cpu/m68k/qsm.h index e1bf33bc12..9853978115 100644 --- a/c/src/exec/score/cpu/m68k/qsm.h +++ b/c/src/exec/score/cpu/m68k/qsm.h @@ -41,10 +41,6 @@ #ifndef _QSM_H_ #define _QSM_H_ - -#include - - /* SAM-- shift and mask */ #undef SAM #define SAM(a,b,c) ((a << b) & c) diff --git a/c/src/exec/score/cpu/m68k/rtems/Makefile.am b/c/src/exec/score/cpu/m68k/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/m68k/rtems/Makefile.am +++ b/c/src/exec/score/cpu/m68k/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/m68k/rtems/score/Makefile.am b/c/src/exec/score/cpu/m68k/rtems/score/Makefile.am index 5be89730ec..fa38bea692 100644 --- a/c/src/exec/score/cpu/m68k/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/m68k/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/m68k/rtems/score/m68k.h b/c/src/exec/score/cpu/m68k/rtems/score/m68k.h index 7408aae231..64639220dd 100644 --- a/c/src/exec/score/cpu/m68k/rtems/score/m68k.h +++ b/c/src/exec/score/cpu/m68k/rtems/score/m68k.h @@ -79,6 +79,15 @@ extern "C" { * by having each model specify which core it uses and then go from there. */ +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. Notice the only exception to this is that + * gcc does not distinguish between CPU32 and CPU32+. This + * feature selection logic is setup such that if RTEMS__mcpu32p__ + * is defined, then CPU32+ rules are used. Otherwise, the safe + * but less efficient CPU32 rules are used for the CPU32+. + */ + #if defined(__mc68020__) #define CPU_MODEL_NAME "m68020" diff --git a/c/src/exec/score/cpu/m68k/sim.h b/c/src/exec/score/cpu/m68k/sim.h index e1c637f9bd..9354412390 100644 --- a/c/src/exec/score/cpu/m68k/sim.h +++ b/c/src/exec/score/cpu/m68k/sim.h @@ -50,13 +50,6 @@ #define _SIM_H_ -/* - * XXX Why is a generic file like this including a bsp specific file? - -#include - */ - - /* SAM-- shift and mask */ #undef SAM #define SAM(a,b,c) ((a << b) & c) diff --git a/c/src/exec/score/cpu/mips/Makefile.am b/c/src/exec/score/cpu/mips/Makefile.am index b54cb49ded..5c13d378e9 100644 --- a/c/src/exec/score/cpu/mips/Makefile.am +++ b/c/src/exec/score/cpu/mips/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/mips/rtems/Makefile.am b/c/src/exec/score/cpu/mips/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/mips/rtems/Makefile.am +++ b/c/src/exec/score/cpu/mips/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/mips/rtems/score/Makefile.am b/c/src/exec/score/cpu/mips/rtems/score/Makefile.am index 728899f945..be1e4fd6b7 100644 --- a/c/src/exec/score/cpu/mips/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/mips/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/mips/rtems/score/mips.h b/c/src/exec/score/cpu/mips/rtems/score/mips.h index 1ff139f604..425d0cc5fd 100644 --- a/c/src/exec/score/cpu/mips/rtems/score/mips.h +++ b/c/src/exec/score/cpu/mips/rtems/score/mips.h @@ -44,7 +44,16 @@ extern "C" { * of the family. */ -#if defined(R4650) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define MIPS64ORION_HAS_FPU 1 + +#elif defined(R4650) #define CPU_MODEL_NAME "R4650" #define MIPS64ORION_HAS_FPU 1 diff --git a/c/src/exec/score/cpu/mips/rtems/score/mips64orion.h b/c/src/exec/score/cpu/mips/rtems/score/mips64orion.h index 1ff139f604..425d0cc5fd 100644 --- a/c/src/exec/score/cpu/mips/rtems/score/mips64orion.h +++ b/c/src/exec/score/cpu/mips/rtems/score/mips64orion.h @@ -44,7 +44,16 @@ extern "C" { * of the family. */ -#if defined(R4650) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define MIPS64ORION_HAS_FPU 1 + +#elif defined(R4650) #define CPU_MODEL_NAME "R4650" #define MIPS64ORION_HAS_FPU 1 diff --git a/c/src/exec/score/cpu/mips64orion/Makefile.am b/c/src/exec/score/cpu/mips64orion/Makefile.am index b54cb49ded..5c13d378e9 100644 --- a/c/src/exec/score/cpu/mips64orion/Makefile.am +++ b/c/src/exec/score/cpu/mips64orion/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/mips64orion/rtems/Makefile.am b/c/src/exec/score/cpu/mips64orion/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/mips64orion/rtems/Makefile.am +++ b/c/src/exec/score/cpu/mips64orion/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/mips64orion/rtems/score/Makefile.am b/c/src/exec/score/cpu/mips64orion/rtems/score/Makefile.am index 728899f945..be1e4fd6b7 100644 --- a/c/src/exec/score/cpu/mips64orion/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/mips64orion/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/mips64orion/rtems/score/mips64orion.h b/c/src/exec/score/cpu/mips64orion/rtems/score/mips64orion.h index 1ff139f604..425d0cc5fd 100644 --- a/c/src/exec/score/cpu/mips64orion/rtems/score/mips64orion.h +++ b/c/src/exec/score/cpu/mips64orion/rtems/score/mips64orion.h @@ -44,7 +44,16 @@ extern "C" { * of the family. */ -#if defined(R4650) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define MIPS64ORION_HAS_FPU 1 + +#elif defined(R4650) #define CPU_MODEL_NAME "R4650" #define MIPS64ORION_HAS_FPU 1 diff --git a/c/src/exec/score/cpu/no_cpu/Makefile.am b/c/src/exec/score/cpu/no_cpu/Makefile.am index 29ff8e77ff..b055a2d202 100644 --- a/c/src/exec/score/cpu/no_cpu/Makefile.am +++ b/c/src/exec/score/cpu/no_cpu/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -35,7 +35,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/no_cpu/cpu.c b/c/src/exec/score/cpu/no_cpu/cpu.c index 4711eb6703..9df97623ba 100644 --- a/c/src/exec/score/cpu/no_cpu/cpu.c +++ b/c/src/exec/score/cpu/no_cpu/cpu.c @@ -23,6 +23,10 @@ * INPUT PARAMETERS: * cpu_table - CPU table to initialize * thread_dispatch - address of disptaching routine + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ @@ -59,6 +63,10 @@ void _CPU_Initialize( /*PAGE * * _CPU_ISR_Get_level + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ unsigned32 _CPU_ISR_Get_level( void ) @@ -73,6 +81,10 @@ unsigned32 _CPU_ISR_Get_level( void ) /*PAGE * * _CPU_ISR_install_raw_handler + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_ISR_install_raw_handler( @@ -101,6 +113,10 @@ void _CPU_ISR_install_raw_handler( * * Output parameters: NONE * + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_ISR_install_vector( @@ -130,6 +146,10 @@ void _CPU_ISR_install_vector( /*PAGE * * _CPU_Install_interrupt_stack + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Install_interrupt_stack( void ) @@ -151,6 +171,10 @@ void _CPU_Install_interrupt_stack( void ) * to stop the DMA if the CPU were put in IDLE mode. This might * also be a problem with other on-chip peripherals. So use this * hook with caution. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Thread_Idle_body( void ) diff --git a/c/src/exec/score/cpu/no_cpu/cpu_asm.c b/c/src/exec/score/cpu/no_cpu/cpu_asm.c index 5a5728a2f8..2ee4067f6c 100644 --- a/c/src/exec/score/cpu/no_cpu/cpu_asm.c +++ b/c/src/exec/score/cpu/no_cpu/cpu_asm.c @@ -37,6 +37,10 @@ * the ** and a similarly named routine in this file is passed something * like a (Context_Control_fp *). The general rule on making this decision * is to avoid writing assembly language. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_save_fp( @@ -56,6 +60,10 @@ void _CPU_Context_save_fp( * the ** and a similarly named routine in this file is passed something * like a (Context_Control_fp *). The general rule on making this decision * is to avoid writing assembly language. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_restore_fp( @@ -67,6 +75,10 @@ void _CPU_Context_restore_fp( /* _CPU_Context_switch * * This routine performs a normal non-FP context switch. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_switch( @@ -83,6 +95,10 @@ void _CPU_Context_switch( * efficient manner. It may simply be a label in _CPU_Context_switch. * * NOTE: May be unnecessary to reload some registers. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_restore( @@ -95,6 +111,9 @@ void _CPU_Context_restore( * * This routine provides the RTEMS interrupt management. * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _ISR_Handler() diff --git a/c/src/exec/score/cpu/no_cpu/rtems.c b/c/src/exec/score/cpu/no_cpu/rtems.c index 9e7e0b66d7..4310d55fed 100644 --- a/c/src/exec/score/cpu/no_cpu/rtems.c +++ b/c/src/exec/score/cpu/no_cpu/rtems.c @@ -36,6 +36,10 @@ * preserving the arguments. The directive should not realize * it has been "wrapped" in this way. The table "_Entry_points" * is used to look up the directive. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void RTEMS() diff --git a/c/src/exec/score/cpu/no_cpu/rtems/Makefile.am b/c/src/exec/score/cpu/no_cpu/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/no_cpu/rtems/Makefile.am +++ b/c/src/exec/score/cpu/no_cpu/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/no_cpu/rtems/score/Makefile.am b/c/src/exec/score/cpu/no_cpu/rtems/score/Makefile.am index 61e7148453..972d50d860 100644 --- a/c/src/exec/score/cpu/no_cpu/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/no_cpu/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/no_cpu/rtems/score/cpu.h b/c/src/exec/score/cpu/no_cpu/rtems/score/cpu.h index da99e163cc..b2eeaa84ce 100644 --- a/c/src/exec/score/cpu/no_cpu/rtems/score/cpu.h +++ b/c/src/exec/score/cpu/no_cpu/rtems/score/cpu.h @@ -42,6 +42,10 @@ extern "C" { * something calls _Thread_Enable_dispatch which in turns calls * _Thread_Dispatch. If the enable dispatch is inlined, then * one subroutine call is avoided entirely.] + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_INLINE_ENABLE_DISPATCH FALSE @@ -62,6 +66,10 @@ extern "C" { * to unroll the loop. It is important to note that on some CPUs, this * code is the longest interrupt disable period in RTEMS. So it is * necessary to strike a balance when setting this parameter. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_UNROLL_ENQUEUE_PRIORITY TRUE @@ -88,6 +96,10 @@ extern "C" { * possible that both are FALSE for a particular CPU. Although it * is unclear what that would imply about the interrupt processing * procedure on that CPU. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE @@ -105,6 +117,10 @@ extern "C" { * possible that both are FALSE for a particular CPU. Although it * is unclear what that would imply about the interrupt processing * procedure on that CPU. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE @@ -117,6 +133,10 @@ extern "C" { * * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_ALLOCATE_INTERRUPT_STACK TRUE @@ -125,6 +145,10 @@ extern "C" { * Does the RTEMS invoke the user's ISR with the vector number and * a pointer to the saved interrupt frame (1) or just the vector * number (0)? + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_ISR_PASSES_FRAME_POINTER 0 @@ -143,6 +167,16 @@ extern "C" { * example, it would be possible to have an i386_nofp CPU model * which set this to false to indicate that you have an i386 without * an i387 and wish to leave floating point support out of RTEMS. + * + * The CPU_SOFTWARE_FP is used to indicate whether or not there + * is software implemented floating point that must be context + * switched. The determination of whether or not this applies + * is very tool specific and the state saved/restored is also + * compiler specific. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #if ( NO_CPU_HAS_FPU == 1 ) @@ -150,6 +184,7 @@ extern "C" { #else #define CPU_HARDWARE_FP FALSE #endif +#define CPU_SOFTWARE_FP FALSE /* * Are all tasks RTEMS_FLOATING_POINT tasks implicitly? @@ -165,6 +200,10 @@ extern "C" { * In this case, this option should be TRUE. * * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_ALL_TASKS_ARE_FP TRUE @@ -179,6 +218,10 @@ extern "C" { * Setting this to TRUE negatively impacts the time required to preempt * the IDLE task from an interrupt because the floating point context * must be saved as part of the preemption. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_IDLE_TASK_IS_FP FALSE @@ -207,6 +250,10 @@ extern "C" { * until a context switch is made to another, different FP task. * Thus in a system with only one FP task, the FP context will never * be saved or restored. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_USE_DEFERRED_FP_SWITCH TRUE @@ -230,6 +277,10 @@ extern "C" { * 1. BSP provided * 2. CPU dependent (if provided) * 3. generic (if no BSP and no CPU dependent) + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_PROVIDES_IDLE_THREAD_BODY TRUE @@ -240,6 +291,10 @@ extern "C" { * * If TRUE, then the grows upward. * If FALSE, then the grows toward smaller addresses. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_STACK_GROWS_UP TRUE @@ -262,6 +317,10 @@ extern "C" { * To benefit from using this, the data must be heavily * used so it will stay in the cache and used frequently enough * in the executive to justify turning this on. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_STRUCTURE_ALIGNMENT @@ -269,6 +328,10 @@ extern "C" { /* * Define what is required to specify how the network to host conversion * routines are handled. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE @@ -279,6 +342,10 @@ extern "C" { * The following defines the number of bits actually used in the * interrupt field of the task mode. How those bits map to the * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level(). + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_MODES_INTERRUPT_MASK 0x00000001 @@ -288,6 +355,10 @@ extern "C" { * * Examples structures include the descriptor tables from the i386 * and the processor control structure on the i960ca. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ /* may need to put some structures here. */ @@ -325,6 +396,10 @@ extern "C" { * to figure out the exact format -- only the size. Of course, although * this is enough information for RTEMS, it is probably not enough for * a debugger such as gdb. But that is another problem. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ typedef struct { @@ -344,6 +419,10 @@ typedef struct { /* * The following table contains the information required to configure * the XXX processor specific parameters. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ typedef struct { @@ -364,10 +443,18 @@ typedef struct { /* * Macros to access required entires in the CPU Table are in * the file rtems/system.h. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ /* * Macros to access NO_CPU specific additions to the CPU Table + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ /* There are no CPU specific additions to the CPU Table for this port. */ @@ -377,6 +464,10 @@ typedef struct { * to generate an "uninitialized" FP context. It is filled in by * _CPU_Initialize and copied into the task's FP context area during * _CPU_Context_Initialize. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; @@ -392,6 +483,10 @@ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; * * NOTE: These two variables are required if the macro * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ SCORE_EXTERN void *_CPU_Interrupt_stack_low; @@ -405,12 +500,20 @@ SCORE_EXTERN void *_CPU_Interrupt_stack_high; * and contains the address of the routine _Thread_Dispatch. This * can make it easier to invoke that routine at the end of the interrupt * sequence (if a dispatch is necessary). + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * Nothing prevents the porter from declaring more CPU specific variables. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ /* XXX: if needed, put more variables here */ @@ -420,6 +523,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * will not be a "sizeof" because the format of the floating point * area is not defined -- only the size is. This is usually on * CPUs with a "floating point save context" instruction. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp ) @@ -428,6 +535,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * Amount of extra stack (above minimum stack size) required by * MPCI receive server thread. Remember that in a multiprocessor * system this thread must exist and be able to process all directives. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0 @@ -435,6 +546,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * This defines the number of entries in the ISR_Vector_table managed * by RTEMS. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_INTERRUPT_NUMBER_OF_VECTORS 32 @@ -443,6 +558,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * Should be large enough to run all RTEMS tests. This insures * that a "reasonable" small application should not have any problems. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_STACK_MINIMUM_SIZE (1024*4) @@ -450,6 +569,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * CPU's worst alignment requirement for data types on a byte boundary. This * alignment does not take into account the requirements for the stack. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_ALIGNMENT 8 @@ -462,8 +585,20 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap, * then this should be set to CPU_ALIGNMENT. * - * NOTE: This does not have to be a power of 2. It does have to - * be greater or equal to than CPU_ALIGNMENT. + * NOTE: This does not have to be a power of 2 although it should be + * a multiple of 2 greater than or equal to 2. The requirement + * to be a multiple of 2 is because the heap uses the least + * significant field of the front and back flags to indicate + * that a block is in use or free. So you do not want any odd + * length blocks really putting length data in that bit. + * + * On byte oriented architectures, CPU_HEAP_ALIGNMENT normally will + * have to be greater or equal to than CPU_ALIGNMENT to ensure that + * elements allocated from the heap meet all restrictions. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT @@ -478,6 +613,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * * NOTE: This does not have to be a power of 2. It does have to * be greater or equal to than CPU_ALIGNMENT. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT @@ -489,6 +628,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * is strict enough for the stack, then this should be set to 0. * * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_STACK_ALIGNMENT 0 @@ -498,6 +641,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * Disable all interrupts for an RTEMS critical section. The previous * level is returned in _level. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_ISR_Disable( _isr_cookie ) \ @@ -509,6 +656,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * Enable interrupts to the previous level (returned by _CPU_ISR_Disable). * This indicates the end of an RTEMS critical section. The parameter * _level is not modified. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_ISR_Enable( _isr_cookie ) \ @@ -520,6 +671,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * disabling them again. This is used to divide long RTEMS critical * sections into two or more parts. The parameter _level is not * modified. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_ISR_Flash( _isr_cookie ) \ @@ -537,6 +692,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * via the rtems_task_mode directive. * * The get routine usually must be implemented as a subroutine. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_ISR_Set_level( new_level ) \ @@ -568,6 +727,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * point thread. This is typically only used on CPUs where the * FPU may be easily disabled by software such as on the SPARC * where the PSR contains an enable FPU bit. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ @@ -583,6 +746,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * case. Context_Restore should work most of the time. It will * not work if restarting self conflicts with the stack frame * assumptions of restoring a context. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_Context_Restart_self( _the_context ) \ @@ -600,6 +767,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * from the base of the context area. Finally some FP units provide * a "dump context" instruction which could fill in from high to low * or low to high based on the whim of the CPU designers. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_Context_Fp_start( _base, _offset ) \ @@ -615,6 +786,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * * Other models include (1) not doing anything, and (2) putting * a "null FP status word" in the correct place in the FP context. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_Context_Initialize_fp( _destination ) \ @@ -630,6 +805,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * This routine copies _error into a known place -- typically a stack * location or a register, optionally disables interrupts, and * halts/stops the CPU. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define _CPU_Fatal_halt( _error ) \ @@ -693,6 +872,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * * where bit_set_table[ 16 ] has values which indicate the first * bit set + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #define CPU_USE_GENERIC_BITFIELD_CODE TRUE @@ -713,6 +896,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * This routine builds the mask which corresponds to the bit fields * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion * for that routine. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) @@ -727,6 +914,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * _CPU_Bitfield_Find_first_bit() into something suitable for use as * a major or minor component of a priority. See the discussion * for that routine. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) @@ -744,6 +935,10 @@ unsigned32 _CPU_ISR_Get_level( void ); * _CPU_Initialize * * This routine performs CPU dependent initialization. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Initialize( @@ -756,6 +951,10 @@ void _CPU_Initialize( * * This routine installs a "raw" interrupt handler directly into the * processor's vector table. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_ISR_install_raw_handler( @@ -768,6 +967,10 @@ void _CPU_ISR_install_raw_handler( * _CPU_ISR_install_vector * * This routine installs an interrupt vector. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_ISR_install_vector( @@ -783,6 +986,10 @@ void _CPU_ISR_install_vector( * * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK * is TRUE. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Install_interrupt_stack( void ); @@ -794,6 +1001,10 @@ void _CPU_Install_interrupt_stack( void ); * * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY * is TRUE. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Thread_Idle_body( void ); @@ -802,6 +1013,10 @@ void _CPU_Thread_Idle_body( void ); * _CPU_Context_switch * * This routine switches from the run context to the heir context. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_switch( @@ -816,6 +1031,10 @@ void _CPU_Context_switch( * efficient manner. It may simply be a label in _CPU_Context_switch. * * NOTE: May be unnecessary to reload some registers. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_restore( @@ -826,6 +1045,10 @@ void _CPU_Context_restore( * _CPU_Context_save_fp * * This routine saves the floating point context passed to it. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_save_fp( @@ -836,6 +1059,10 @@ void _CPU_Context_save_fp( * _CPU_Context_restore_fp * * This routine restores the floating point context passed to it. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ void _CPU_Context_restore_fp( @@ -860,6 +1087,10 @@ void _CPU_Context_restore_fp( * endian. Another good reason is that on some CPUs, the endian bit * endianness for ALL fetches -- both code and data -- so the code * will be fetched incorrectly. + * + * NO_CPU Specific Information: + * + * XXX document implementation including references if appropriate */ static inline unsigned int CPU_swap_u32( diff --git a/c/src/exec/score/cpu/no_cpu/rtems/score/no_cpu.h b/c/src/exec/score/cpu/no_cpu/rtems/score/no_cpu.h index 3f374d5500..6708a7abbd 100644 --- a/c/src/exec/score/cpu/no_cpu/rtems/score/no_cpu.h +++ b/c/src/exec/score/cpu/no_cpu/rtems/score/no_cpu.h @@ -1,6 +1,6 @@ /* no_cpu.h * - * This file is an example (i.e. "no CPU") of the file which is + * This file is an example (i.e. no CPU) of the file which is * created for each CPU family port of RTEMS. * * @@ -24,16 +24,28 @@ extern "C" { /* * This file contains the information required to build - * RTEMS for a particular member of the "no cpu" - * family when executing in protected mode. It does - * this by setting variables to indicate which implementation - * dependent features are present in a particular member - * of the family. + * RTEMS for a particular member of the no CPU family. + * It does this by setting variables to indicate which + * implementation dependent features are present in a particular + * member of the family. + * + * This is a good place to list all the known CPU models + * that this port supports and which RTEMS CPU model they correspond + * to. */ -#if defined(no_cpu) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define NOCPU_HAS_FPU 1 + +#elif defined(no_cpu) -#define CPU_MODEL_NAME "no_cpu" +#define CPU_MODEL_NAME "no_cpu_model" #define NOCPU_HAS_FPU 1 #else diff --git a/c/src/exec/score/cpu/powerpc/Makefile.am b/c/src/exec/score/cpu/powerpc/Makefile.am index db1cf0888a..cbddc2bca7 100644 --- a/c/src/exec/score/cpu/powerpc/Makefile.am +++ b/c/src/exec/score/cpu/powerpc/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal diff --git a/c/src/exec/score/cpu/powerpc/new_exception_processing/Makefile.am b/c/src/exec/score/cpu/powerpc/new_exception_processing/Makefile.am index c3195b159d..1f4affe8f4 100644 --- a/c/src/exec/score/cpu/powerpc/new_exception_processing/Makefile.am +++ b/c/src/exec/score/cpu/powerpc/new_exception_processing/Makefile.am @@ -9,7 +9,7 @@ C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o) ROOT_H_FILES = RTEMS_SCORE_H_FILES = cpu.h c_isr.inl -noinst_HEADERS = $(ROOT_H_FILES) $(RTEMS_SCORE_H_FILES) +noinst_HEADERS = $(ROOT_H_FILES) $(RTEMS_SCORE_H_FILES) S_FILES = cpu_asm.S S_O_FILES = $(S_FILES:%.S=${ARCH}/%.o) @@ -21,11 +21,9 @@ include $(top_srcdir)/../../../../../../automake/lib.am # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(PROJECT_INCLUDE)/rtems/score \ -$(ROOT_H_FILES:%=$(PROJECT_INCLUDE)/%) \ -$(RTEMS_SCORE_H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems/score \ + $(ROOT_H_FILES:%=$(PROJECT_INCLUDE)/%) \ + $(RTEMS_SCORE_H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) ##TMPINSTALL_FILES += \ ##$(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o @@ -55,10 +53,8 @@ all-local: $(ARCH) $(PREINSTALL_FILES) $(REL) ## all-local: $(ARCH)/rtems.o all-local: $(TMPINSTALL_FILES) -clean-local: - $(RM) -r ../o-optimize ../o-debug ../o-profile +CLEANDIRS = ../o-optimize ../o-debug ../o-profile -EXTRA_DIST = \ -$(C_FILES) $(S_FILES) +EXTRA_DIST = $(C_FILES) $(S_FILES) include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/exec/score/cpu/powerpc/old_exception_processing/Makefile.am b/c/src/exec/score/cpu/powerpc/old_exception_processing/Makefile.am index afd66502eb..9629808140 100644 --- a/c/src/exec/score/cpu/powerpc/old_exception_processing/Makefile.am +++ b/c/src/exec/score/cpu/powerpc/old_exception_processing/Makefile.am @@ -19,14 +19,11 @@ S_O_FILES = $(S_FILES:%.S=${ARCH}/%.o) include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../../../../automake/lib.am -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(PROJECT_INCLUDE)/rtems/score \ -$(ROOT_H_FILES:%=$(PROJECT_INCLUDE)/%) \ -$(RTEMS_SCORE_H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems/score \ + $(ROOT_H_FILES:%=$(PROJECT_INCLUDE)/%) \ + $(RTEMS_SCORE_H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) -TMPINSTALL_FILES += \ -$(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o: $(ARCH)/rtems.o $(INSTALL_DATA) $< $@ @@ -49,18 +46,12 @@ $(REL): $(C_O_FILES) $(S_O_FILES) test -d ../$(ARCH) || mkdir ../$(ARCH) $(make-rel) -all-local: $(ARCH) $(PREINSTALL_FILES) $(REL) -all-local: $(ARCH)/rtems.o -all-local: $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(REL) $(ARCH)/rtems.o $(TMPINSTALL_FILES) -clean-local: - $(RM) -r ../o-optimize ../o-debug ../o-profile +CLEANDIRS = ../o-optimize ../o-debug ../o-profile UNUSED_FILES = irq_stub.S -EXTRA_DIST = \ -TODO \ -rtems.S \ -$(C_FILES) $(S_FILES) $(UNUSED_FILES) +EXTRA_DIST = TODO rtems.S $(C_FILES) $(S_FILES) $(UNUSED_FILES) include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/exec/score/cpu/powerpc/old_exception_processing/irq_stub.S b/c/src/exec/score/cpu/powerpc/old_exception_processing/irq_stub.S index 76c8927305..400cccdf73 100644 --- a/c/src/exec/score/cpu/powerpc/old_exception_processing/irq_stub.S +++ b/c/src/exec/score/cpu/powerpc/old_exception_processing/irq_stub.S @@ -55,7 +55,9 @@ lis r11,_CPU_IRQ_info@ha addi r11,r11,_CPU_IRQ_info@l #endif +#if ( PPC_USE_DATA_CACHE ) dcbt r0, r11 +#endif stw r5, IP_CR(r1) stw r6, IP_CTR(r1) stw r7, IP_XER(r1) diff --git a/c/src/exec/score/cpu/powerpc/rtems/score/ppc.h b/c/src/exec/score/cpu/powerpc/rtems/score/ppc.h index ff93f9b1b3..83a54bfa25 100644 --- a/c/src/exec/score/cpu/powerpc/rtems/score/ppc.h +++ b/c/src/exec/score/cpu/powerpc/rtems/score/ppc.h @@ -94,7 +94,28 @@ extern "C" { #define PPC_LOW_POWER_MODE_NONE 0 #define PPC_LOW_POWER_MODE_STANDARD 1 -#if defined(ppc403) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define PPC_ALIGNMENT 4 +#define PPC_CACHE_ALIGNMENT 16 +#define PPC_HAS_RFCI 1 +#define PPC_HAS_FPU 0 +#define PPC_USE_MULTIPLE 1 +#define PPC_I_CACHE 2048 +#define PPC_D_CACHE 1024 +#define PPC_DEBUG_MODEL PPC_DEBUG_MODEL_STANDARD +#define PPC_HAS_EXCEPTION_PREFIX 0 +#define PPC_HAS_EVPR 0 +#define PPC_INTERRUPT_MAX 16 +#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_STANDARD +#define PPC_HAS_DOUBLE 0 + +#elif defined(ppc403) /* * IBM 403 * @@ -129,7 +150,7 @@ extern "C" { #define PPC_ALIGNMENT 4 #define PPC_CACHE_ALIGNMENT 16 #define PPC_I_CACHE 4096 -#define PPC_I_CACHE 0 +#define PPC_D_CACHE 0 #elif defined(ppc601) @@ -281,6 +302,14 @@ extern "C" { */ #define PPC_ABI_EABI 3 +/* + * Default to the EABI used by current GNU tools + */ + +#ifndef PPC_ABI +#define PPC_ABI PPC_ABI_EABI +#endif + #if (PPC_ABI == PPC_ABI_POWEROPEN) #define PPC_STACK_ALIGNMENT 8 #elif (PPC_ABI == PPC_ABI_GCC27) @@ -309,6 +338,14 @@ extern "C" { #define PPC_ASM_ELF 0 #define PPC_ASM_XCOFF 1 +/* + * Default to the assembler format used by the current GNU tools. + */ + +#ifndef PPC_ASM +#define PPC_ASM PPC_ASM_ELF +#endif + /* * Use the default debug scheme defined in the architectural specification * if another model has not been specified. @@ -449,7 +486,14 @@ extern "C" { #define PPC_IRQ_FIT (PPC_STD_IRQ_LAST+2) /*0x01010- Fixed int. timer */ #define PPC_IRQ_WATCHDOG (PPC_STD_IRQ_LAST+3) /*0x01020- Watchdog timer */ #define PPC_IRQ_DEBUG (PPC_STD_IRQ_LAST+4) /*0x02000- Debug exceptions */ -#define PPC_IRQ_LAST PPC_IRQ_DEBUG +#define PPC_IRQ_LAST PPC_IRQ_DEBUG + +#elif defined(mpc505) || defined(mpc509) +#define PPC_IRQ_SOFTEMU (PPC_STD_IRQ_LAST+1) /* Software emulation. */ +#define PPC_IRQ_DATA_BP (PPC_STD_IRQ_LAST+ 2) +#define PPC_IRQ_INST_BP (PPC_STD_IRQ_LAST+ 3) +#define PPC_IRQ_MEXT_BP (PPC_STD_IRQ_LAST+ 4) +#define PPC_IRQ_NMEXT_BP (PPC_STD_IRQ_LAST+ 5) #elif defined(ppc601) #define PPC_IRQ_TRACE (PPC_STD_IRQ_LAST+1) /*0x02000-Run/Trace Exception*/ diff --git a/c/src/exec/score/cpu/powerpc/shared/Makefile.am b/c/src/exec/score/cpu/powerpc/shared/Makefile.am index a2d0fb5f96..7aae87d8d3 100644 --- a/c/src/exec/score/cpu/powerpc/shared/Makefile.am +++ b/c/src/exec/score/cpu/powerpc/shared/Makefile.am @@ -12,11 +12,9 @@ noinst_HEADERS = $(ROOT_H_FILES) $(RTEMS_SCORE_H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE) \ -$(PROJECT_INCLUDE)/rtems/score \ -$(ROOT_H_FILES:%.h=$(PROJECT_INCLUDE)/%.h) \ -$(RTEMS_SCORE_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/rtems/score \ + $(ROOT_H_FILES:%.h=$(PROJECT_INCLUDE)/%.h) \ + $(RTEMS_SCORE_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE): $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/powerpc/shared/ppc.h b/c/src/exec/score/cpu/powerpc/shared/ppc.h index ff93f9b1b3..83a54bfa25 100644 --- a/c/src/exec/score/cpu/powerpc/shared/ppc.h +++ b/c/src/exec/score/cpu/powerpc/shared/ppc.h @@ -94,7 +94,28 @@ extern "C" { #define PPC_LOW_POWER_MODE_NONE 0 #define PPC_LOW_POWER_MODE_STANDARD 1 -#if defined(ppc403) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define PPC_ALIGNMENT 4 +#define PPC_CACHE_ALIGNMENT 16 +#define PPC_HAS_RFCI 1 +#define PPC_HAS_FPU 0 +#define PPC_USE_MULTIPLE 1 +#define PPC_I_CACHE 2048 +#define PPC_D_CACHE 1024 +#define PPC_DEBUG_MODEL PPC_DEBUG_MODEL_STANDARD +#define PPC_HAS_EXCEPTION_PREFIX 0 +#define PPC_HAS_EVPR 0 +#define PPC_INTERRUPT_MAX 16 +#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_STANDARD +#define PPC_HAS_DOUBLE 0 + +#elif defined(ppc403) /* * IBM 403 * @@ -129,7 +150,7 @@ extern "C" { #define PPC_ALIGNMENT 4 #define PPC_CACHE_ALIGNMENT 16 #define PPC_I_CACHE 4096 -#define PPC_I_CACHE 0 +#define PPC_D_CACHE 0 #elif defined(ppc601) @@ -281,6 +302,14 @@ extern "C" { */ #define PPC_ABI_EABI 3 +/* + * Default to the EABI used by current GNU tools + */ + +#ifndef PPC_ABI +#define PPC_ABI PPC_ABI_EABI +#endif + #if (PPC_ABI == PPC_ABI_POWEROPEN) #define PPC_STACK_ALIGNMENT 8 #elif (PPC_ABI == PPC_ABI_GCC27) @@ -309,6 +338,14 @@ extern "C" { #define PPC_ASM_ELF 0 #define PPC_ASM_XCOFF 1 +/* + * Default to the assembler format used by the current GNU tools. + */ + +#ifndef PPC_ASM +#define PPC_ASM PPC_ASM_ELF +#endif + /* * Use the default debug scheme defined in the architectural specification * if another model has not been specified. @@ -449,7 +486,14 @@ extern "C" { #define PPC_IRQ_FIT (PPC_STD_IRQ_LAST+2) /*0x01010- Fixed int. timer */ #define PPC_IRQ_WATCHDOG (PPC_STD_IRQ_LAST+3) /*0x01020- Watchdog timer */ #define PPC_IRQ_DEBUG (PPC_STD_IRQ_LAST+4) /*0x02000- Debug exceptions */ -#define PPC_IRQ_LAST PPC_IRQ_DEBUG +#define PPC_IRQ_LAST PPC_IRQ_DEBUG + +#elif defined(mpc505) || defined(mpc509) +#define PPC_IRQ_SOFTEMU (PPC_STD_IRQ_LAST+1) /* Software emulation. */ +#define PPC_IRQ_DATA_BP (PPC_STD_IRQ_LAST+ 2) +#define PPC_IRQ_INST_BP (PPC_STD_IRQ_LAST+ 3) +#define PPC_IRQ_MEXT_BP (PPC_STD_IRQ_LAST+ 4) +#define PPC_IRQ_NMEXT_BP (PPC_STD_IRQ_LAST+ 5) #elif defined(ppc601) #define PPC_IRQ_TRACE (PPC_STD_IRQ_LAST+1) /*0x02000-Run/Trace Exception*/ diff --git a/c/src/exec/score/cpu/sh/Makefile.am b/c/src/exec/score/cpu/sh/Makefile.am index 680b7151dc..d6c8f3ae05 100644 --- a/c/src/exec/score/cpu/sh/Makefile.am +++ b/c/src/exec/score/cpu/sh/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -35,7 +35,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/sh/rtems/Makefile.am b/c/src/exec/score/cpu/sh/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/sh/rtems/Makefile.am +++ b/c/src/exec/score/cpu/sh/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/sh/rtems/score/Makefile.am b/c/src/exec/score/cpu/sh/rtems/score/Makefile.am index 3008d9cef9..f650704221 100644 --- a/c/src/exec/score/cpu/sh/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/sh/rtems/score/Makefile.am @@ -1,23 +1,20 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 H_FILES = cpu.h shtypes.h sh.h sh_io.h isp$(RTEMS_CPU_MODEL).h \ io$(RTEMS_CPU_MODEL).h -noinst_HEADERS = \ - cpu.h shtypes.h sh.h sh_io.h \ - iosh7032.h ispsh7032.h \ +noinst_HEADERS = cpu.h shtypes.h sh.h sh_io.h iosh7032.h ispsh7032.h \ iosh7045.h ispsh7045.h # # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/sh/rtems/score/sh.h b/c/src/exec/score/cpu/sh/rtems/score/sh.h index 4417e6a99d..26c633c190 100644 --- a/c/src/exec/score/cpu/sh/rtems/score/sh.h +++ b/c/src/exec/score/cpu/sh/rtems/score/sh.h @@ -39,7 +39,17 @@ extern "C" { * dependent features are present in a particular member of the family. */ -#if defined(sh7032) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define SH_HAS_FPU 0 +#define SH_HAS_SEPARATE_STACKS 1 + +#elif defined(sh7032) #define CPU_MODEL_NAME "SH7032" #define SH_HAS_FPU 0 diff --git a/c/src/exec/score/cpu/sparc/Makefile.am b/c/src/exec/score/cpu/sparc/Makefile.am index 6ae4472920..493f2c8e76 100644 --- a/c/src/exec/score/cpu/sparc/Makefile.am +++ b/c/src/exec/score/cpu/sparc/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal @@ -38,7 +38,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%=$(PROJECT_INCLUDE)/%) TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/rtems$(LIB_VARIANT).o -all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) $(TMPINSTALL_FILES) +all-local: $(ARCH) $(PREINSTALL_FILES) $(rtems_cpu_rel_OBJECTS) $(REL) \ + $(TMPINSTALL_FILES) .PRECIOUS: $(REL) diff --git a/c/src/exec/score/cpu/sparc/rtems/Makefile.am b/c/src/exec/score/cpu/sparc/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/sparc/rtems/Makefile.am +++ b/c/src/exec/score/cpu/sparc/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/sparc/rtems/score/Makefile.am b/c/src/exec/score/cpu/sparc/rtems/score/Makefile.am index 602dce7cd5..f73fc35933 100644 --- a/c/src/exec/score/cpu/sparc/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/sparc/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -11,9 +11,8 @@ noinst_HEADERS = $(H_FILES) # (OPTIONAL) Add local stuff here using += # -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/sparc/rtems/score/sparc.h b/c/src/exec/score/cpu/sparc/rtems/score/sparc.h index 0cb44c2df9..9fa52533cd 100644 --- a/c/src/exec/score/cpu/sparc/rtems/score/sparc.h +++ b/c/src/exec/score/cpu/sparc/rtems/score/sparc.h @@ -54,7 +54,19 @@ extern "C" { * */ -#if defined(erc32) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" +#define SPARC_HAS_FPU 1 +#define SPARC_HAS_BITSCAN 0 +#define SPARC_NUMBER_OF_REGISTER_WINDOWS 8 +#define SPARC_HAS_LOW_POWER_MODE 1 + +#elif defined(erc32) #define CPU_MODEL_NAME "erc32" #define SPARC_HAS_FPU 1 diff --git a/c/src/exec/score/cpu/unix/Makefile.am b/c/src/exec/score/cpu/unix/Makefile.am index e619852a38..3aadc93da0 100644 --- a/c/src/exec/score/cpu/unix/Makefile.am +++ b/c/src/exec/score/cpu/unix/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal diff --git a/c/src/exec/score/cpu/unix/cpu.c b/c/src/exec/score/cpu/unix/cpu.c index 7f9f9c8047..96c706451d 100644 --- a/c/src/exec/score/cpu/unix/cpu.c +++ b/c/src/exec/score/cpu/unix/cpu.c @@ -42,7 +42,7 @@ typedef struct { jmp_buf regs; - int isr_level; + int isr_level; } Context_Control_overlay; void _CPU_Signal_initialize(void); @@ -99,7 +99,9 @@ void _CPU_ISR_From_CPU_Init() (void) sigfillset(&_CPU_Signal_mask); (void) sigdelset(&_CPU_Signal_mask, SIGTRAP); (void) sigdelset(&_CPU_Signal_mask, SIGABRT); +#if !defined(__CYGWIN__) (void) sigdelset(&_CPU_Signal_mask, SIGIOT); +#endif (void) sigdelset(&_CPU_Signal_mask, SIGCONT); (void) sigdelset(&_CPU_Signal_mask, SIGSEGV); (void) sigdelset(&_CPU_Signal_mask, SIGBUS); @@ -198,7 +200,9 @@ void _CPU_Context_From_CPU_Init() * get default values to use in _CPU_Context_Initialize() */ - + if ( sizeof(Context_Control_overlay) < sizeof(Context_Control) ) + _CPU_Fatal_halt( 0xdeadfood ); + (void) memset( &_CPU_Context_Default_with_ISRs_enabled, 0, @@ -274,6 +278,15 @@ void _CPU_Initialize( void (*thread_dispatch) /* ignored on this CPU */ ) { + /* + * If something happened where the public Context_Control is not + * at least as large as the private Context_Control_overlay, then + * we are in trouble. + */ + + if ( sizeof(Context_Control_overlay) > sizeof(Context_Control) ) + _CPU_Fatal_error(0x100 + 1); + /* * The thread_dispatch argument is the address of the entry point * for the routine called at the end of an ISR once it has been @@ -482,11 +495,11 @@ void _CPU_Context_Initialize( */ if ( _new_level == 0 ) - *_the_context = *(Context_Control *) - &_CPU_Context_Default_with_ISRs_enabled; + *(Context_Control_overlay *)_the_context = + _CPU_Context_Default_with_ISRs_enabled; else - *_the_context = *(Context_Control *) - &_CPU_Context_Default_with_ISRs_disabled; + *(Context_Control_overlay *)_the_context = + _CPU_Context_Default_with_ISRs_disabled; addr = (unsigned32 *)_the_context; @@ -806,7 +819,9 @@ void _CPU_Stray_signal(int sig_num) case SIGBUS: case SIGSEGV: case SIGTERM: +#if !defined(__CYGWIN__) case SIGIOT: +#endif _CPU_Fatal_error(0x100 + sig_num); } } diff --git a/c/src/exec/score/cpu/unix/rtems/Makefile.am b/c/src/exec/score/cpu/unix/rtems/Makefile.am index 900930a502..ef7df82af7 100644 --- a/c/src/exec/score/cpu/unix/rtems/Makefile.am +++ b/c/src/exec/score/cpu/unix/rtems/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/c/src/exec/score/cpu/unix/rtems/score/Makefile.am b/c/src/exec/score/cpu/unix/rtems/score/Makefile.am index 06c1e6e614..52d5d046ef 100644 --- a/c/src/exec/score/cpu/unix/rtems/score/Makefile.am +++ b/c/src/exec/score/cpu/unix/rtems/score/Makefile.am @@ -1,6 +1,6 @@ -## +## ## $Id$ -## +## AUTOMAKE_OPTIONS = foreign 1.4 @@ -20,10 +20,9 @@ unixsize.h: $(GENSIZE) cpu.h CLEANFILES = unixsize.h -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(STATIC_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) \ -$(GENERIC_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(STATIC_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) \ + $(GENERIC_H_FILES:%.h=$(PROJECT_INCLUDE)/rtems/score/%.h) $(PROJECT_INCLUDE)/rtems/score: $(mkinstalldirs) $@ diff --git a/c/src/exec/score/cpu/unix/rtems/score/cpu.h b/c/src/exec/score/cpu/unix/rtems/score/cpu.h index 75eb07af74..698d900515 100644 --- a/c/src/exec/score/cpu/unix/rtems/score/cpu.h +++ b/c/src/exec/score/cpu/unix/rtems/score/cpu.h @@ -378,7 +378,7 @@ extern "C" { #endif /* - * For Linux 1.1 + * For i386 targets */ #ifdef RTEMS_UNIXLIB @@ -389,7 +389,18 @@ extern "C" { #define ESP_OFF 3 #define ESI_OFF 4 #define EDI_OFF 5 +#elif defined(__CYGWIN__) +#define EAX_OFF 0 +#define EBX_OFF 1 +#define ECX_OFF 2 +#define EDX_OFF 3 +#define ESI_OFF 4 +#define EDI_OFF 5 +#define EBP_OFF 6 +#define ESP_OFF 7 +#define RET_OFF 8 #else +/* Linux */ #define EBX_OFF 0 #define ESI_OFF 1 #define EDI_OFF 2 diff --git a/c/src/exec/score/cpu/unix/rtems/score/unix.h b/c/src/exec/score/cpu/unix/rtems/score/unix.h index 26ef8ca4e4..e8a0c7bdd6 100644 --- a/c/src/exec/score/cpu/unix/rtems/score/unix.h +++ b/c/src/exec/score/cpu/unix/rtems/score/unix.h @@ -29,7 +29,15 @@ extern "C" { * of the family. */ -#if defined(hpux) +#if defined(rtems_multilib) +/* + * Figure out all CPU Model Feature Flags based upon compiler + * predefines. + */ + +#define CPU_MODEL_NAME "rtems_multilib" + +#elif defined(hpux) #define CPU_MODEL_NAME "HP-UX" @@ -37,13 +45,13 @@ extern "C" { #define CPU_MODEL_NAME "Solaris" -#elif defined(__linux__) +#elif defined(__linux__) || defined(linux) #define CPU_MODEL_NAME "Linux" -#elif defined(linux) +#elif defined(__CYGWIN__) -#define CPU_MODEL_NAME "Linux" +#define CPU_MODEL_NAME "Cygwin" #elif defined(__FreeBSD__) diff --git a/c/src/exec/score/include/rtems/Makefile.am b/c/src/exec/score/include/rtems/Makefile.am index f09b99a313..f4ac2b1717 100644 --- a/c/src/exec/score/include/rtems/Makefile.am +++ b/c/src/exec/score/include/rtems/Makefile.am @@ -8,18 +8,15 @@ H_FILES = debug.h system.h noinst_HEADERS = $(H_FILES) -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems \ -$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems \ + $(noinst_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) $(PROJECT_INCLUDE)/rtems: @$(mkinstalldirs) $@ $(PROJECT_INCLUDE)/rtems/%.h: %.h $(INSTALL_DATA) $< $@ -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) SUBDIRS = score diff --git a/c/src/exec/score/include/rtems/score/Makefile.am b/c/src/exec/score/include/rtems/score/Makefile.am index 4507d51b33..01468381c6 100644 --- a/c/src/exec/score/include/rtems/score/Makefile.am +++ b/c/src/exec/score/include/rtems/score/Makefile.am @@ -11,10 +11,10 @@ include $(RTEMS_ROOT)/make/leaf.cfg MP_H_FILES = mpci.h mppkt.h objectmp.h threadmp.h # H_FILES that get installed in the rtems/score subdirectoy -STD_H_FILES = address.h apiext.h bitfield.h chain.h context.h copyrt.h coremsg.h \ - coremutex.h coresem.h heap.h interr.h isr.h object.h priority.h stack.h \ - states.h sysstate.h thread.h threadq.h tod.h tqdata.h userext.h \ - watchdog.h wkspace.h +STD_H_FILES = address.h apiext.h bitfield.h chain.h context.h copyrt.h \ + coremsg.h coremutex.h coresem.h heap.h interr.h isr.h object.h \ + priority.h stack.h states.h sysstate.h thread.h threadq.h tod.h tqdata.h \ + userext.h watchdog.h wkspace.h TARGOPTS = targopts.h if HAS_MP @@ -23,9 +23,8 @@ else H_FILES = $(STD_H_FILES) $(TARGOPTS) endif -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(H_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) $(PROJECT_INCLUDE)/rtems/score: @$(mkinstalldirs) $@ @@ -45,7 +44,7 @@ CLEANFILES += $(TARGOPTS) RTEMS_CPU_DEFINED = $(subst .,_,$(RTEMS_CPU)) # make the target dependent options file -$(TARGOPTS): +$(TARGOPTS): @echo "/* target board dependent options file */" >$@ @echo "/* automatically generated -- DO NOT EDIT!! */" >>$@ @echo >>$@ @@ -89,7 +88,7 @@ $(TARGOPTS): @echo >>$@ @echo "#endif" >>$@ -all: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) EXTRA_DIST = $(STD_H_FILES) $(MP_H_FILES) diff --git a/c/src/exec/score/include/rtems/score/thread.h b/c/src/exec/score/include/rtems/score/thread.h index ec48864a9f..4c8032f558 100644 --- a/c/src/exec/score/include/rtems/score/thread.h +++ b/c/src/exec/score/include/rtems/score/thread.h @@ -94,7 +94,8 @@ struct rtems_task_variable_tt; struct rtems_task_variable_tt { struct rtems_task_variable_tt *next; void **ptr; - void *var; + void *gval; + void *tval; void (*dtor)(void *); }; diff --git a/c/src/exec/score/include/rtems/system.h b/c/src/exec/score/include/rtems/system.h index 6db19e8c62..b1a2382ea4 100644 --- a/c/src/exec/score/include/rtems/system.h +++ b/c/src/exec/score/include/rtems/system.h @@ -187,10 +187,10 @@ SCORE_EXTERN rtems_cpu_table _CPU_Table; /* CPU dependent info */ (_CPU_Table.stack_free_hook) /* - * XXX weird RTEMS stuff + * XXX weird RTEMS stuff that probably should be somewhere else. */ -#define RTEMS_MAXIMUM_NAME_LENGTH 4 +#define RTEMS_MAXIMUM_NAME_LENGTH sizeof(rtems_name) #ifdef __cplusplus } diff --git a/c/src/exec/score/inline/rtems/score/Makefile.am b/c/src/exec/score/inline/rtems/score/Makefile.am index e7dc3a2cde..6b6083f625 100644 --- a/c/src/exec/score/inline/rtems/score/Makefile.am +++ b/c/src/exec/score/inline/rtems/score/Makefile.am @@ -21,9 +21,8 @@ endif noinst_HEADERS = $(STD_I_FILES) $(MP_I_FILES) if INLINE -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/score/%) $(PROJECT_INCLUDE)/rtems/score: @$(mkinstalldirs) $@ @@ -31,8 +30,6 @@ $(PROJECT_INCLUDE)/rtems/score/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/score/macros/rtems/score/Makefile.am b/c/src/exec/score/macros/rtems/score/Makefile.am index 0ac48e0386..4260e15c08 100644 --- a/c/src/exec/score/macros/rtems/score/Makefile.am +++ b/c/src/exec/score/macros/rtems/score/Makefile.am @@ -7,9 +7,10 @@ AUTOMAKE_OPTIONS = foreign 1.4 ## We only build multiprocessing related files if HAS_MP was defined MP_I_FILES = mppkt.inl objectmp.inl threadmp.inl -STD_I_FILES = address.inl chain.inl coremsg.inl coremutex.inl coresem.inl heap.inl \ - isr.inl object.inl priority.inl stack.inl states.inl sysstate.inl \ - thread.inl tod.inl tqdata.inl userext.inl watchdog.inl wkspace.inl +STD_I_FILES = address.inl chain.inl coremsg.inl coremutex.inl coresem.inl \ + heap.inl isr.inl object.inl priority.inl stack.inl states.inl \ + sysstate.inl thread.inl tod.inl tqdata.inl userext.inl watchdog.inl \ + wkspace.inl noinst_HEADERS = $(STD_I_FILES) $(MP_I_FILES) @@ -20,9 +21,8 @@ else I_FILES = $(STD_I_FILES endif -PREINSTALL_FILES = \ -$(PROJECT_INCLUDE)/rtems/score \ -$(I_FILES:%=$(PROJECT_INCLUDE)/rtems/score%) +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score \ + $(I_FILES:%=$(PROJECT_INCLUDE)/rtems/score%) $(PROJECT_INCLUDE)/rtems/score: @$(mkinstalldirs) $@ @@ -30,8 +30,6 @@ $(PROJECT_INCLUDE)/rtems/score/%.inl: %.inl $(INSTALL_DATA) $< $@ endif -all-am: $(PREINSTALL_FILES) -debug-am: $(PREINSTALL_FILES) -profile-am: $(PREINSTALL_FILES) +all-local: $(PREINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/exec/score/macros/rtems/score/address.inl b/c/src/exec/score/macros/rtems/score/address.inl index 379aaca6cc..2f14aa633a 100644 --- a/c/src/exec/score/macros/rtems/score/address.inl +++ b/c/src/exec/score/macros/rtems/score/address.inl @@ -52,7 +52,7 @@ */ #define _Addresses_Is_aligned( _address ) \ - ( ( (unsigned32)(_address) % 4 ) == 0 ) + ( ( (unsigned32)(_address) % CPU_ALIGNMENT ) == 0 ) /*PAGE * diff --git a/c/src/exec/score/src/Makefile.am b/c/src/exec/score/src/Makefile.am index f5914fdb37..c348a606f1 100644 --- a/c/src/exec/score/src/Makefile.am +++ b/c/src/exec/score/src/Makefile.am @@ -71,9 +71,8 @@ OBJS = $(C_O_FILES) # AM_CPPFLAGS += -D__RTEMS_INSIDE__ -AM_CFLAGS += $(CFLAGS_OS_V) -all: ${ARCH} ${OBJS} +all-local: ${ARCH} ${OBJS} EXTRA_DIST = $(STD_C_FILES) $(MP_C_FILES) Unlimited.txt diff --git a/c/src/exec/score/src/objectcopynamestring.c b/c/src/exec/score/src/objectcopynamestring.c index cd0779d546..eb196f3d25 100644 --- a/c/src/exec/score/src/objectcopynamestring.c +++ b/c/src/exec/score/src/objectcopynamestring.c @@ -39,7 +39,10 @@ void _Objects_Copy_name_string( unsigned8 *source_p = (unsigned8 *) source; unsigned8 *destination_p = (unsigned8 *) destination; - do { - *destination_p++ = *source_p; - } while ( *source_p++ ); + *destination_p = '\0'; + if ( source_p ) { + do { + *destination_p++ = *source_p; + } while ( *source_p++ ); + } } diff --git a/c/src/exec/wrapup/itron/Makefile.am b/c/src/exec/wrapup/itron/Makefile.am index 58ceeb6d05..8f801355df 100644 --- a/c/src/exec/wrapup/itron/Makefile.am +++ b/c/src/exec/wrapup/itron/Makefile.am @@ -21,13 +21,12 @@ OBJS = $(ITRON_OBJS) $(LIB): ${OBJS} $(make-library) -ITRON_LIB = \ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a +ITRON_LIB = $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) $(INSTALL_DATA) $< $@ -all: ${ARCH} $(LIB) $(TMPINSTALL_FILES) +all-local: ${ARCH} $(LIB) $(TMPINSTALL_FILES) endif diff --git a/c/src/exec/wrapup/posix/Makefile.am b/c/src/exec/wrapup/posix/Makefile.am index d80634763d..7bcd49438a 100644 --- a/c/src/exec/wrapup/posix/Makefile.am +++ b/c/src/exec/wrapup/posix/Makefile.am @@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 if HAS_POSIX LIBNAME = libposix -LIB = $(ARCH)/$(LIBNAME).a +LIB = $(ARCH)/$(LIBNAME).a endif include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg @@ -21,13 +21,12 @@ OBJS = $(POSIX_OBJS) $(LIB): ${OBJS} $(make-library) -POSIX_LIB = \ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a +POSIX_LIB = $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) $(INSTALL_DATA) $< $@ -all: ${ARCH} $(LIB) $(TMPINSTALL_FILES) +all-local: ${ARCH} $(LIB) $(TMPINSTALL_FILES) endif diff --git a/c/src/exec/wrapup/rtems/Makefile.am b/c/src/exec/wrapup/rtems/Makefile.am index d2cadc9a58..4659f409ce 100644 --- a/c/src/exec/wrapup/rtems/Makefile.am +++ b/c/src/exec/wrapup/rtems/Makefile.am @@ -25,12 +25,11 @@ $(LIB): ${OBJS} $(SIZE_RTEMS) @RTEMS_BSP@ $(ARCH) \ >$(PROJECT_RELEASE)/lib/sizeinfo$(LIB_VARIANT).txt -TMPINSTALL_FILES += \ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a +TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) $(INSTALL_DATA) $< $@ -all: ${ARCH} $(TMPINSTALL_FILES) +all-local: ${ARCH} $(TMPINSTALL_FILES) include $(top_srcdir)/../../../automake/local.am -- cgit v1.2.3