From af6b0e296605c82d710385f41117396a54d4d625 Mon Sep 17 00:00:00 2001 From: Vijay Kumar Banerjee Date: Thu, 11 Feb 2021 22:13:34 -0700 Subject: Add libmisc and librpc from RTEMS cpukit --- libmisc/dummy-networking.c | 42 + libmisc/err.c | 64 ++ libmisc/err.h | 85 ++ libmisc/internal.h | 36 + libmisc/main_ifconfig.c | 275 +++++ libmisc/main_netstats.c | 137 +++ libmisc/main_ping.c | 1982 ++++++++++++++++++++++++++++++++ libmisc/main_route.c | 151 +++ libmisc/mon-network.c | 342 ++++++ libmisc/sysexits.h | 116 ++ librpc/README_RTEMS | 64 ++ librpc/include/rpcsvc/bootparam_prot.x | 103 ++ librpc/include/rpcsvc/crypt.x | 91 ++ librpc/include/rpcsvc/key_prot.x | 282 +++++ librpc/include/rpcsvc/klm_prot.x | 139 +++ librpc/include/rpcsvc/mount.x | 257 +++++ librpc/include/rpcsvc/nfs_prot.x | 1265 ++++++++++++++++++++ librpc/include/rpcsvc/nis.x | 466 ++++++++ librpc/include/rpcsvc/nis_cache.x | 87 ++ librpc/include/rpcsvc/nis_callback.x | 76 ++ librpc/include/rpcsvc/nis_db.h | 164 +++ librpc/include/rpcsvc/nis_object.x | 317 +++++ librpc/include/rpcsvc/nis_tags.h | 137 +++ librpc/include/rpcsvc/nislib.h | 317 +++++ librpc/include/rpcsvc/nlm_prot.x | 183 +++ librpc/include/rpcsvc/pmap_prot.x | 284 +++++ librpc/include/rpcsvc/rex.x | 235 ++++ librpc/include/rpcsvc/rnusers.x | 122 ++ librpc/include/rpcsvc/rquota.x | 67 ++ librpc/include/rpcsvc/rstat.x | 151 +++ librpc/include/rpcsvc/rwall.x | 57 + librpc/include/rpcsvc/sm_inter.x | 122 ++ librpc/include/rpcsvc/spray.x | 90 ++ librpc/include/rpcsvc/yp.x | 379 ++++++ librpc/include/rpcsvc/yp_prot.h | 330 ++++++ librpc/include/rpcsvc/ypclnt.h | 93 ++ librpc/include/rpcsvc/yppasswd.x | 75 ++ librpc/include/rpcsvc/ypupdate_prot.x | 88 ++ librpc/include/rpcsvc/ypxfrd.x | 173 +++ librpc/src/rpc/DISCLAIMER | 28 + librpc/src/rpc/README | 233 ++++ librpc/src/rpc/auth_none.c | 140 +++ librpc/src/rpc/auth_unix.c | 347 ++++++ librpc/src/rpc/authunix_prot.c | 73 ++ librpc/src/rpc/bindresvport.3 | 106 ++ librpc/src/rpc/bindresvport.c | 162 +++ librpc/src/rpc/clnt_generic.c | 147 +++ librpc/src/rpc/clnt_perror.c | 261 +++++ librpc/src/rpc/clnt_raw.c | 250 ++++ librpc/src/rpc/clnt_simple.c | 129 +++ librpc/src/rpc/clnt_tcp.c | 608 ++++++++++ librpc/src/rpc/clnt_udp.c | 582 ++++++++++ librpc/src/rpc/des_crypt.3 | 130 +++ librpc/src/rpc/get_myaddress.c | 143 +++ librpc/src/rpc/getrpcent.3 | 98 ++ librpc/src/rpc/getrpcent.c | 303 +++++ librpc/src/rpc/getrpcport.3 | 31 + librpc/src/rpc/getrpcport.c | 71 ++ librpc/src/rpc/netname.c | 141 +++ librpc/src/rpc/netnamer.c | 333 ++++++ librpc/src/rpc/pmap_clnt.c | 153 +++ librpc/src/rpc/pmap_getmaps.c | 93 ++ librpc/src/rpc/pmap_getport.c | 99 ++ librpc/src/rpc/pmap_prot.c | 65 ++ librpc/src/rpc/pmap_prot2.c | 124 ++ librpc/src/rpc/pmap_rmt.c | 444 +++++++ librpc/src/rpc/publickey.3 | 47 + librpc/src/rpc/publickey.5 | 38 + librpc/src/rpc/rpc.3 | 1767 ++++++++++++++++++++++++++++ librpc/src/rpc/rpc.5 | 35 + librpc/src/rpc/rpc_callmsg.c | 198 ++++ librpc/src/rpc/rpc_commondata.c | 47 + librpc/src/rpc/rpc_dtablesize.c | 67 ++ librpc/src/rpc/rpc_prot.c | 338 ++++++ librpc/src/rpc/rpc_secure.3 | 254 ++++ librpc/src/rpc/rpcdname.c | 86 ++ librpc/src/rpc/rstat.1 | 58 + librpc/src/rpc/rstat_svc.8 | 22 + librpc/src/rpc/rtems-rpc-config.h | 40 + librpc/src/rpc/rtems_portmapper.c | 502 ++++++++ librpc/src/rpc/rtems_rpc.c | 127 ++ librpc/src/rpc/rtime.3 | 47 + librpc/src/rpc/rtime.c | 165 +++ librpc/src/rpc/svc.c | 502 ++++++++ librpc/src/rpc/svc_auth.c | 222 ++++ librpc/src/rpc/svc_auth_unix.c | 154 +++ librpc/src/rpc/svc_raw.c | 175 +++ librpc/src/rpc/svc_run.c | 91 ++ librpc/src/rpc/svc_simple.c | 163 +++ librpc/src/rpc/svc_tcp.c | 491 ++++++++ librpc/src/rpc/svc_udp.c | 486 ++++++++ librpc/src/xdr/xdr.3 | 837 ++++++++++++++ librpc/src/xdr/xdr.c | 858 ++++++++++++++ librpc/src/xdr/xdr_array.c | 160 +++ librpc/src/xdr/xdr_float.c | 344 ++++++ librpc/src/xdr/xdr_mem.c | 245 ++++ librpc/src/xdr/xdr_rec.c | 608 ++++++++++ librpc/src/xdr/xdr_reference.c | 142 +++ librpc/src/xdr/xdr_sizeof.c | 167 +++ librpc/src/xdr/xdr_stdio.c | 194 ++++ lnetworking.py | 2 +- 101 files changed, 24416 insertions(+), 1 deletion(-) create mode 100644 libmisc/dummy-networking.c create mode 100644 libmisc/err.c create mode 100644 libmisc/err.h create mode 100644 libmisc/internal.h create mode 100644 libmisc/main_ifconfig.c create mode 100644 libmisc/main_netstats.c create mode 100644 libmisc/main_ping.c create mode 100644 libmisc/main_route.c create mode 100644 libmisc/mon-network.c create mode 100644 libmisc/sysexits.h create mode 100644 librpc/README_RTEMS create mode 100644 librpc/include/rpcsvc/bootparam_prot.x create mode 100644 librpc/include/rpcsvc/crypt.x create mode 100644 librpc/include/rpcsvc/key_prot.x create mode 100644 librpc/include/rpcsvc/klm_prot.x create mode 100644 librpc/include/rpcsvc/mount.x create mode 100644 librpc/include/rpcsvc/nfs_prot.x create mode 100644 librpc/include/rpcsvc/nis.x create mode 100644 librpc/include/rpcsvc/nis_cache.x create mode 100644 librpc/include/rpcsvc/nis_callback.x create mode 100644 librpc/include/rpcsvc/nis_db.h create mode 100644 librpc/include/rpcsvc/nis_object.x create mode 100644 librpc/include/rpcsvc/nis_tags.h create mode 100644 librpc/include/rpcsvc/nislib.h create mode 100644 librpc/include/rpcsvc/nlm_prot.x create mode 100644 librpc/include/rpcsvc/pmap_prot.x create mode 100644 librpc/include/rpcsvc/rex.x create mode 100644 librpc/include/rpcsvc/rnusers.x create mode 100644 librpc/include/rpcsvc/rquota.x create mode 100644 librpc/include/rpcsvc/rstat.x create mode 100644 librpc/include/rpcsvc/rwall.x create mode 100644 librpc/include/rpcsvc/sm_inter.x create mode 100644 librpc/include/rpcsvc/spray.x create mode 100644 librpc/include/rpcsvc/yp.x create mode 100644 librpc/include/rpcsvc/yp_prot.h create mode 100644 librpc/include/rpcsvc/ypclnt.h create mode 100644 librpc/include/rpcsvc/yppasswd.x create mode 100644 librpc/include/rpcsvc/ypupdate_prot.x create mode 100644 librpc/include/rpcsvc/ypxfrd.x create mode 100644 librpc/src/rpc/DISCLAIMER create mode 100644 librpc/src/rpc/README create mode 100644 librpc/src/rpc/auth_none.c create mode 100644 librpc/src/rpc/auth_unix.c create mode 100644 librpc/src/rpc/authunix_prot.c create mode 100644 librpc/src/rpc/bindresvport.3 create mode 100644 librpc/src/rpc/bindresvport.c create mode 100644 librpc/src/rpc/clnt_generic.c create mode 100644 librpc/src/rpc/clnt_perror.c create mode 100644 librpc/src/rpc/clnt_raw.c create mode 100644 librpc/src/rpc/clnt_simple.c create mode 100644 librpc/src/rpc/clnt_tcp.c create mode 100644 librpc/src/rpc/clnt_udp.c create mode 100644 librpc/src/rpc/des_crypt.3 create mode 100644 librpc/src/rpc/get_myaddress.c create mode 100644 librpc/src/rpc/getrpcent.3 create mode 100644 librpc/src/rpc/getrpcent.c create mode 100644 librpc/src/rpc/getrpcport.3 create mode 100644 librpc/src/rpc/getrpcport.c create mode 100644 librpc/src/rpc/netname.c create mode 100644 librpc/src/rpc/netnamer.c create mode 100644 librpc/src/rpc/pmap_clnt.c create mode 100644 librpc/src/rpc/pmap_getmaps.c create mode 100644 librpc/src/rpc/pmap_getport.c create mode 100644 librpc/src/rpc/pmap_prot.c create mode 100644 librpc/src/rpc/pmap_prot2.c create mode 100644 librpc/src/rpc/pmap_rmt.c create mode 100644 librpc/src/rpc/publickey.3 create mode 100644 librpc/src/rpc/publickey.5 create mode 100644 librpc/src/rpc/rpc.3 create mode 100644 librpc/src/rpc/rpc.5 create mode 100644 librpc/src/rpc/rpc_callmsg.c create mode 100644 librpc/src/rpc/rpc_commondata.c create mode 100644 librpc/src/rpc/rpc_dtablesize.c create mode 100644 librpc/src/rpc/rpc_prot.c create mode 100644 librpc/src/rpc/rpc_secure.3 create mode 100644 librpc/src/rpc/rpcdname.c create mode 100644 librpc/src/rpc/rstat.1 create mode 100644 librpc/src/rpc/rstat_svc.8 create mode 100644 librpc/src/rpc/rtems-rpc-config.h create mode 100644 librpc/src/rpc/rtems_portmapper.c create mode 100644 librpc/src/rpc/rtems_rpc.c create mode 100644 librpc/src/rpc/rtime.3 create mode 100644 librpc/src/rpc/rtime.c create mode 100644 librpc/src/rpc/svc.c create mode 100644 librpc/src/rpc/svc_auth.c create mode 100644 librpc/src/rpc/svc_auth_unix.c create mode 100644 librpc/src/rpc/svc_raw.c create mode 100644 librpc/src/rpc/svc_run.c create mode 100644 librpc/src/rpc/svc_simple.c create mode 100644 librpc/src/rpc/svc_tcp.c create mode 100644 librpc/src/rpc/svc_udp.c create mode 100644 librpc/src/xdr/xdr.3 create mode 100644 librpc/src/xdr/xdr.c create mode 100644 librpc/src/xdr/xdr_array.c create mode 100644 librpc/src/xdr/xdr_float.c create mode 100644 librpc/src/xdr/xdr_mem.c create mode 100644 librpc/src/xdr/xdr_rec.c create mode 100644 librpc/src/xdr/xdr_reference.c create mode 100644 librpc/src/xdr/xdr_sizeof.c create mode 100644 librpc/src/xdr/xdr_stdio.c diff --git a/libmisc/dummy-networking.c b/libmisc/dummy-networking.c new file mode 100644 index 0000000..379e23e --- /dev/null +++ b/libmisc/dummy-networking.c @@ -0,0 +1,42 @@ +/* + * Dummy configuration file + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* Loopback Network Configuration */ +#if defined(RTEMS_NETWORKING) + #include + #include + #include + + struct rtems_bsdnet_config rtems_bsdnet_config = { + NULL, /* Network interface */ + NULL, /* Use fixed network configuration */ + 0, /* Default network task priority */ + 0, /* Default mbuf capacity */ + 0, /* Default mbuf cluster capacity */ + "testSystem", /* Host name */ + "nowhere.com", /* Domain name */ + "127.0.0.1", /* Gateway */ + "127.0.0.1", /* Log host */ + {"127.0.0.1" }, /* Name server(s) */ + {"127.0.0.1" }, /* NTP server(s) */ + 1, /* sb_efficiency */ + 0, /* udp_tx_buf_size */ + 0, /* udp_rx_buf_size */ + 0, /* tcp_tx_buf_size */ + 0 /* tcp_rx_buf_size */ + }; +#endif diff --git a/libmisc/err.c b/libmisc/err.c new file mode 100644 index 0000000..fff022a --- /dev/null +++ b/libmisc/err.c @@ -0,0 +1,64 @@ +/* $NetBSD: err.c,v 1.25 2005/09/13 13:51:50 christos Exp $ */ + +/*- + * Copyright (c) 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. 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: err.c,v 1.25 2005/09/13 13:51:50 christos Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include "err.h" +#include + +#ifdef __weak_alias +__weak_alias(err, _err) +#endif + +__dead void +err(jmp_buf* exit_jmp, int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verr(exit_jmp, eval, fmt, ap); + va_end(ap); +} diff --git a/libmisc/err.h b/libmisc/err.h new file mode 100644 index 0000000..6e64e8d --- /dev/null +++ b/libmisc/err.h @@ -0,0 +1,85 @@ +/* $NetBSD: err.h,v 1.14 2005/02/03 04:39:32 perry Exp $ */ + +/*- + * Copyright (c) 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. 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. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two + * places ( and ), so if we include one + * of them here we may collide with the utility's includes. It's unreasonable + * for utilities to have to include one of them to include err.h, so we get + * _BSD_VA_LIST_ from and use it. + */ +#include +#include + +#include +#define _BSD_VA_LIST_ va_list + +#define __dead + +#define err rtems_shell_err +#define verr rtems_shell_verr +#define errx rtems_shell_errx +#define verrx rtems_shell_verrx +#define warn rtems_shell_warn +#define vwarn rtems_shell_vwarn +#define warnx rtems_shell_warnx +#define vwarnx rtems_shell_vwarnx + +#include +#include + +extern jmp_buf rtems_shell_bsd_exit_recover; + +__BEGIN_DECLS +__dead void err(jmp_buf*, int, const char *, ...) + __attribute__((__noreturn__, __format__(__printf__, 3, 4))); +__dead void verr(jmp_buf*, int, const char *, _BSD_VA_LIST_) + __attribute__((__noreturn__, __format__(__printf__, 3, 0))); +__dead void errx(jmp_buf*, int, const char *, ...) + __attribute__((__noreturn__, __format__(__printf__, 3, 4))); +__dead void verrx(jmp_buf*, int, const char *, _BSD_VA_LIST_) + __attribute__((__noreturn__, __format__(__printf__, 3, 0))); +void warn(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +void vwarn(const char *, _BSD_VA_LIST_) + __attribute__((__format__(__printf__, 1, 0))); +void warnx(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +void vwarnx(const char *, _BSD_VA_LIST_) + __attribute__((__format__(__printf__, 1, 0))); +__END_DECLS + +#endif /* !_ERR_H_ */ diff --git a/libmisc/internal.h b/libmisc/internal.h new file mode 100644 index 0000000..2d042ae --- /dev/null +++ b/libmisc/internal.h @@ -0,0 +1,36 @@ +/* + * Shell Internal Information + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_SHELL_INTERNAL_H +#define _RTEMS_SHELL_INTERNAL_H + +#include + +extern rtems_shell_cmd_t * rtems_shell_first_cmd; +extern rtems_shell_topic_t * rtems_shell_first_topic; + +extern void rtems_shell_register_monitor_commands(void); + +extern void rtems_shell_print_heap_info( + const char *c, + const Heap_Information *h +); + +extern void rtems_shell_print_heap_stats( + const Heap_Statistics *s +); + +extern void rtems_shell_print_unified_work_area_message(void); + +#include + +extern void strmode(mode_t mode, char *p); +extern const char *user_from_uid(uid_t uid, int nouser); +extern char *group_from_gid(gid_t gid, int nogroup); + +#endif diff --git a/libmisc/main_ifconfig.c b/libmisc/main_ifconfig.c new file mode 100644 index 0000000..c19048f --- /dev/null +++ b/libmisc/main_ifconfig.c @@ -0,0 +1,275 @@ +/* + * IFCONFIG Command Implmentation + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include "internal.h" + + +static const char IFCONFIG_USAGE[] = + "ifconfig [iface]\n" + "ifconfig iface options | addr\n" + " iface: name of the interface\n" + " options: iface \n" + " up: bring the interface up\n" + " down: take the interface down\n" + " netmask addr: network mask\n" + " broadcast addr: boardcast address\n" + " pointopoint addr: destination address for a PTP link\n" + "\n" + " addr: IP address"; + + +static int rtems_shell_main_ifconfig( + int argc, + char *argv[] +) +{ + struct sockaddr_in ipaddr; + struct sockaddr_in dstaddr; + struct sockaddr_in netmask; + struct sockaddr_in broadcast; + char *iface = NULL; + int f_ip = 0; + int f_ptp = 0; + int f_netmask = 0; + int f_up = 0; + int f_down = 0; + int f_bcast = 0; + int f_usage = 0; + int cur_idx; + int rc; + int flags; + + memset(&ipaddr, 0, sizeof(ipaddr)); + memset(&dstaddr, 0, sizeof(dstaddr)); + memset(&netmask, 0, sizeof(netmask)); + memset(&broadcast, 0, sizeof(broadcast)); + + ipaddr.sin_len = sizeof(ipaddr); + ipaddr.sin_family = AF_INET; + + dstaddr.sin_len = sizeof(dstaddr); + dstaddr.sin_family = AF_INET; + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + + broadcast.sin_len = sizeof(broadcast); + broadcast.sin_family = AF_INET; + + cur_idx = 0; + if (argc <= 1) { + /* display all interfaces */ + iface = NULL; + cur_idx += 1; + } else { + if ( 0 == strcmp( "--help", argv[1] ) ) { + f_usage = 1; + cur_idx += 2; + } else if ( 0 == strcmp( "-help", argv[1] ) ) { + f_usage = 1; + cur_idx += 2; + } else { + iface = argv[1]; + if ( argc >= 3 ) { + if (isdigit((unsigned char)*argv[2])) { + if (inet_pton(AF_INET, argv[2], &ipaddr.sin_addr) < 0) { + printf("bad ip address: %s\n", argv[2]); + return 0; + } + f_ip = 1; + cur_idx += 3; + } else { + cur_idx += 2; + } + } else { + cur_idx += 2; + } + } + } + + if ((f_down !=0) && (f_ip != 0)) { + f_up = 1; + } + + while(argc > cur_idx) { + if (strcmp(argv[cur_idx], "up") == 0) { + f_up = 1; + if (f_down != 0) { + printf("Can't make interface up and down\n"); + return -1; + } + } else if(strcmp(argv[cur_idx], "down") == 0) { + f_down = 1; + if (f_up != 0) { + printf("Can't make interface up and down\n"); + return -1; + } + } else if(strcmp(argv[cur_idx], "netmask") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No netmask address\n"); + return -1; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &netmask.sin_addr) < 0) { + printf("bad netmask: %s\n", argv[cur_idx]); + return -1; + } + f_netmask = 1; + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "broadcast") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No broadcast address\n"); + return -1; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &broadcast.sin_addr) < 0) { + printf("bad broadcast: %s\n", argv[cur_idx]); + return -1; + } + f_bcast = 1; + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "pointopoint") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No pointopoint address\n"); + return -1; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &dstaddr.sin_addr) < 0) { + printf("bad pointopoint: %s\n", argv[cur_idx]); + return -1; + } + f_ptp = 1; + cur_idx += 1; + } else { + printf("Bad parameter: %s\n", argv[cur_idx]); + return -1; + } + cur_idx += 1; + } + + printf("ifconfig "); + if (iface != NULL) { + printf("%s ", iface); + if (f_ip != 0) { + char str[256]; + inet_ntop(AF_INET, &ipaddr.sin_addr, str, 256); + printf("%s ", str); + } + + if (f_netmask != 0) { + char str[256]; + inet_ntop(AF_INET, &netmask.sin_addr, str, 256); + printf("netmask %s ", str); + } + + if (f_bcast != 0) { + char str[256]; + inet_ntop(AF_INET, &broadcast.sin_addr, str, 256); + printf("broadcast %s ", str); + } + + if (f_ptp != 0) { + char str[256]; + inet_ntop(AF_INET, &dstaddr.sin_addr, str, 256); + printf("pointopoint %s ", str); + } + + if (f_up != 0) { + printf("up\n"); + } else if (f_down != 0) { + printf("down\n"); + } else { + printf("\n"); + } + } else if (f_usage != 0) { + printf ( "\n" ); + printf ( IFCONFIG_USAGE ); + } + + if ( ! f_usage ) { + if ((iface == NULL) || ((f_ip == 0) && (f_down == 0) && (f_up == 0))) { + rtems_bsdnet_show_if_stats(); + return 0; + } + } + + flags = 0; + if (f_netmask) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFNETMASK, &netmask); + if (rc < 0) { + printf("Could not set netmask: %s\n", strerror(errno)); + return -1; + } + } + + if (f_bcast) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFBRDADDR, &broadcast); + if (rc < 0) { + printf("Could not set broadcast: %s\n", strerror(errno)); + return -1; + } + } + + if (f_ptp) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFDSTADDR, &dstaddr); + if (rc < 0) { + printf("Could not set destination address: %s\n", strerror(errno)); + return -1; + } + flags |= IFF_POINTOPOINT; + } + + /* This must come _after_ setting the netmask, broadcast addresses */ + if (f_ip) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFADDR, &ipaddr); + if (rc < 0) { + printf("Could not set IP address: %s\n", strerror(errno)); + return -1; + } + } + + if (f_up != 0) { + flags |= IFF_UP; + } + + if ( ! f_usage ) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFFLAGS, &flags); + if (rc < 0) { + printf("Could not set interface flags: %s\n", strerror(errno)); + return -1; + } + } + + return 0; +} + +rtems_shell_cmd_t rtems_shell_IFCONFIG_Command = { + "ifconfig", /* name */ + IFCONFIG_USAGE, /* usage */ + "network", /* topic */ + rtems_shell_main_ifconfig, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/libmisc/main_netstats.c b/libmisc/main_netstats.c new file mode 100644 index 0000000..30007a6 --- /dev/null +++ b/libmisc/main_netstats.c @@ -0,0 +1,137 @@ +/* + * Network Statistics Shell Command Implmentation + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#define __need_getopt_newlib +#include + +#include +#include +#include +#include "internal.h" + +static void netstats_usage(void) +{ + printf( + "netstats [-vAimfpcut] where:\n" + " -A print All statistics\n" + " -i print Inet Routes\n" + " -m print MBUF Statistics\n" + " -f print IF Statistics\n" + " -p print IP Statistics\n" + " -c print ICMP Statistics\n" + " -u print UDP Statistics\n" + " -t print TCP Statistics\n" + ); +} + +static int rtems_shell_main_netstats( /* command */ + int argc, + char *argv[] +) +{ + int option; + int doAll = 0; + int doInetRoutes = 0; + int doMBUFStats = 0; + int doIFStats = 0; + int doIPStats = 0; + int doICMPStats = 0; + int doUDPStats = 0; + int doTCPStats = 0; + int verbose = 0; + struct getopt_data getopt_reent; + + memset(&getopt_reent, 0, sizeof(getopt_data)); + while ( (option = getopt_r( argc, argv, "Aimfpcutv", &getopt_reent)) != -1 ) { + + switch ((char)option) { + case 'A': doAll = 1; break; + case 'i': doInetRoutes = 1; break; + case 'm': doMBUFStats = 1; break; + case 'f': doIFStats = 1; break; + case 'p': doIPStats = 1; break; + case 'c': doICMPStats = 1; break; + case 'u': doUDPStats = 1; break; + case 't': doTCPStats = 1; break; + case 'v': verbose = 1; break; + case '?': + default: + netstats_usage(); + return -1; + } + } + + if ( verbose ) { + printf( + "doAll=%d\n" + "doInetRoutes=%d\n" + "doMBUFStats=%d\n" + "doIFStats=%d\n" + "doIPStats=%d\n" + "doICMPStats=%d\n" + "doUDPStats=%d\n" + "doTCPStats=%d\n", + doAll, + doInetRoutes, + doMBUFStats, + doIFStats, + doIPStats, + doICMPStats, + doUDPStats, + doTCPStats + ); + } + + if ( doInetRoutes == 1 || doAll == 1 ) { + rtems_bsdnet_show_inet_routes(); + } + + if ( doMBUFStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_mbuf_stats(); + } + + if ( doIFStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_if_stats(); + } + + if ( doIPStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_ip_stats(); + } + + if ( doICMPStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_icmp_stats(); + } + + if ( doUDPStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_udp_stats(); + } + + if ( doTCPStats == 1 || doAll == 1 ) { + rtems_bsdnet_show_tcp_stats(); + } + + return 0; +} + +rtems_shell_cmd_t rtems_shell_NETSTATS_Command = { + "netstats", /* name */ + "netstats [-Aimfpcutv]", /* usage */ + "network", /* topic */ + rtems_shell_main_netstats, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/libmisc/main_ping.c b/libmisc/main_ping.c new file mode 100644 index 0000000..05dee34 --- /dev/null +++ b/libmisc/main_ping.c @@ -0,0 +1,1982 @@ +#ifdef __rtems__ +#define __need_getopt_newlib +#include +#endif +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Muuss. + * + * 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. + * 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. + */ + +#if !__rtems__ +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD$"); + +/* + * P I N G . C + * + * Using the Internet Control Message Protocol (ICMP) "ECHO" facility, + * measure round-trip-delays and packet loss across network paths. + * + * Author - + * Mike Muuss + * U. S. Army Ballistic Research Laboratory + * December, 1983 + * + * Status - + * Public Domain. Distribution Unlimited. + * Bugs - + * More statistics could always be gathered. + * This program has to run SUID to ROOT to access the ICMP socket. + */ + +#include /* NB: we rely on this for */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef IPSEC +#include +#endif /*IPSEC*/ + +#include +//#include "err.h" +#include +#if !defined(__rtems__) +#include +#endif +#include +#include +#include +#include +#include +//#include +#include + +#include "err.h" +#include "sysexits.h" +#include +#ifdef __rtems__ +#include +#endif /* __rtems__ */ + +#define INADDR_LEN ((int)sizeof(in_addr_t)) +#define TIMEVAL_LEN ((int)sizeof(struct tv32)) +#define MASK_LEN (ICMP_MASKLEN - ICMP_MINLEN) +#define TS_LEN (ICMP_TSLEN - ICMP_MINLEN) +#define DEFDATALEN 56 /* default data length */ +#define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */ + /* runs out of buffer space */ +#define MAXIPLEN (sizeof(struct ip) + MAX_IPOPTLEN) +#define MAXICMPLEN (ICMP_ADVLENMIN + MAX_IPOPTLEN) +#define MAXWAIT 10000 /* max ms to wait for response */ +#define MAXALARM (60 * 60) /* max seconds for alarm timeout */ +#define MAXTOS 255 + +#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ +#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ +#define SET(bit) (A(bit) |= B(bit)) +#define CLR(bit) (A(bit) &= (~B(bit))) +#define TST(bit) (A(bit) & B(bit)) + +struct tv32 { + int32_t tv32_sec; + int32_t tv32_usec; +}; + +/* various options */ +#if !__rtems__ +int options; +#endif +#define F_FLOOD 0x0001 +#define F_INTERVAL 0x0002 +#define F_NUMERIC 0x0004 +#define F_PINGFILLED 0x0008 +#define F_QUIET 0x0010 +#define F_RROUTE 0x0020 +#define F_SO_DEBUG 0x0040 +#define F_SO_DONTROUTE 0x0080 +#define F_VERBOSE 0x0100 +#define F_QUIET2 0x0200 +#define F_NOLOOP 0x0400 +#define F_MTTL 0x0800 +#define F_MIF 0x1000 +#define F_AUDIBLE 0x2000 +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +#define F_POLICY 0x4000 +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ +#define F_TTL 0x8000 +#define F_MISSED 0x10000 +#define F_ONCE 0x20000 +#define F_HDRINCL 0x40000 +#define F_MASK 0x80000 +#define F_TIME 0x100000 +#define F_SWEEP 0x200000 +#define F_WAITTIME 0x400000 + +/* + * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum + * number of received sequence numbers we can keep track of. Change 128 + * to 8192 for complete accuracy... + */ +#define MAX_DUP_CHK (8 * 128) +#if !__rtems__ +int mx_dup_ck = MAX_DUP_CHK; +char rcvd_tbl[MAX_DUP_CHK / 8]; + +struct sockaddr_in whereto; /* who to ping */ +int datalen = DEFDATALEN; +int maxpayload; +int s; /* socket file descriptor */ +u_char outpackhdr[IP_MAXPACKET], *outpack; +#endif +char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */ +char BSPACE = '\b'; /* characters written for flood */ +char DOT = '.'; +#if !__rtems__ +char *hostname; +char *shostname; +int ident; /* process id to identify our packets */ +int uid; /* cached uid for micro-optimization */ +u_char icmp_type = ICMP_ECHO; +u_char icmp_type_rsp = ICMP_ECHOREPLY; +int phdr_len = 0; +int send_len; + +/* counters */ +long nmissedmax; /* max value of ntransmitted - nreceived - 1 */ +long npackets; /* max packets to transmit */ +long nreceived; /* # of packets we got back */ +long nrepeats; /* number of duplicates */ +long ntransmitted; /* sequence # for outbound packets = #sent */ +long snpackets; /* max packets to transmit in one sweep */ +long snreceived; /* # of packets we got back in this sweep */ +long sntransmitted; /* # of packets we sent in this sweep */ +int sweepmax; /* max value of payload in sweep */ +int sweepmin = 0; /* start value of payload in sweep */ +int sweepincr = 1; /* payload increment in sweep */ +int interval = 1000; /* interval between packets, ms */ +int waittime = MAXWAIT; /* timeout for each packet */ +long nrcvtimeout = 0; /* # of packets we got back after waittime */ + +/* timing */ +int timing; /* flag to do timing */ +double tmin = 999999999.0; /* minimum round trip time */ +double tmax = 0.0; /* maximum round trip time */ +double tsum = 0.0; /* sum of all times, for doing average */ +double tsumsq = 0.0; /* sum of all times squared, for std. dev. */ + +volatile sig_atomic_t finish_up; /* nonzero if we've been told to finish up */ +volatile sig_atomic_t siginfo_p; + +static void fill(char *, char *); +static u_short in_cksum(u_short *, int); +static void check_status(void); +static void finish(void) __dead2; +static void pinger(void); +static char *pr_addr(struct in_addr); +static char *pr_ntime(n_time); +static void pr_icmph(struct icmp *); +static void pr_iph(struct ip *); +static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *); +static void pr_retip(struct ip *); +static void status(int); +static void stopit(int); +static void tvsub(struct timeval *, struct timeval *); +static void usage(void) __dead2; +#endif + +#if __rtems__ +#define CMSG_SPACE(l) (_ALIGN(sizeof(struct cmsghdr)) + _ALIGN(l)) +#define CMSG_LEN(l) (_ALIGN(sizeof(struct cmsghdr)) + (l)) +typedef struct +{ + int options; + int mx_dup_ck; + char rcvd_tbl[MAX_DUP_CHK / 8]; + struct sockaddr_in whereto; + int datalen; + int maxpayload; + int s; + u_char outpackhdr[IP_MAXPACKET]; + u_char *outpack; + char *hostname; + char *shostname; + int ident; + int uid; + u_char icmp_type; + u_char icmp_type_rsp; + int phdr_len; + int send_len; + long nmissedmax; + long npackets; + long nreceived; + long nrepeats; + long ntransmitted; + long snpackets; + long snreceived; + long sntransmitted; + int sweepmax; + int sweepmin; + int sweepincr; + int interval; + int waittime; + long nrcvtimeout; + int timing; + double tmin; + double tmax; + double tsum; + double tsumsq; + volatile sig_atomic_t finish_up; + volatile sig_atomic_t siginfo_p; + + /* main */ + u_char packet[IP_MAXPACKET] __aligned(4); + + /* pr_pack */ + int old_rrlen; + char old_rr[MAX_IPOPTLEN]; + + int exit_code; + jmp_buf exit_jmp; +} rtems_shell_globals_t; + +#define options_ globals->options +#define mx_dup_ck globals->mx_dup_ck +#define rcvd_tbl globals->rcvd_tbl +#define whereto globals->whereto +#define datalen globals->datalen +#define maxpayload globals->maxpayload +#define s globals->s +#define outpackhdr globals->outpackhdr +#define outpack globals->outpack +#define hostname globals->hostname +#define shostname globals->shostname +#define ident globals->ident +#define uid globals->uid +#define icmp_type_ globals->icmp_type +#define icmp_type_rsp globals->icmp_type_rsp +#define phdr_len globals->phdr_len +#define send_len globals->send_len +#define nmissedmax globals->nmissedmax +#define npackets globals->npackets +#define nreceived globals->nreceived +#define nrepeats globals->nrepeats +#define ntransmitted globals->ntransmitted +#define snpackets globals->snpackets +#define snreceived globals->snreceived +#define sntransmitted globals->sntransmitted +#define sweepmax globals->sweepmax +#define sweepmin globals->sweepmin +#define sweepincr globals->sweepincr +#define interval globals->interval +#define waittime globals->waittime +#define nrcvtimeout globals->nrcvtimeout +#define timing globals->timing +#define tmin globals->tmin +#define tmax globals->tmax +#define tsum globals->tsum +#define tsumsq globals->tsumsq +#define finish_up globals->finish_up +#define siginfo_p globals->siginfo_p + +#define old_rrlen globals->old_rrlen +#define old_rr globals->old_rr + +#define packet_ globals->packet + +static u_short in_cksum(u_short *, int); +static char *pr_ntime(n_time); +static void pr_icmph(struct icmp *); +static void pr_iph(struct ip *); +static void pr_retip(struct ip *); +static void stopit(int); +static void tvsub(struct timeval *, struct timeval *); + +#define fill(_a1, _a2) g_fill(_a1, _a2, globals) +static void g_fill(char *_a1, char *_a2, rtems_shell_globals_t* globals); + +#define check_status() g_check_status(globals) +static void g_check_status(rtems_shell_globals_t* globals); + +#define finish() g_finish(globals) +static void g_finish(rtems_shell_globals_t* globals) __dead2; + +#define pinger() g_pinger(globals) +static void g_pinger(rtems_shell_globals_t* globals); + +#define pr_addr(_a1) g_pr_addr(_a1, globals) +static char *g_pr_addr(struct in_addr, rtems_shell_globals_t* globals); + +#define pr_pack(_a1, _a2, _a3, _a4) g_pr_pack(_a1, _a2, _a3, _a4, globals) +static void g_pr_pack(char *, int, struct sockaddr_in *, struct timeval *, rtems_shell_globals_t* globals); + +#define usage() g_usage(globals) +static void g_usage(rtems_shell_globals_t* globals) __dead2; + +static void +rtems_shell_ping_exit (rtems_shell_globals_t* globals, int code) +{ + globals->exit_code = code; + longjmp (globals->exit_jmp, 1); +} + +#define exit(_c) rtems_shell_ping_exit (globals, _c) +#define _exit(_c) exit(_c) + +static int main_ping(int argc, char *const *argv, rtems_shell_globals_t* globals); +static int rtems_shell_main_ping(int argc, char *argv[]) +{ + rtems_shell_globals_t* globals = malloc(sizeof(rtems_shell_globals_t)); + if (!globals) + { + printf("error: no memory\n"); + return 1; + } + memset (globals, 0, sizeof (rtems_shell_globals_t)); + npackets = 5; + datalen = DEFDATALEN; + icmp_type_ = ICMP_ECHO; + icmp_type_rsp = ICMP_ECHOREPLY; + phdr_len = 0; + sweepmin = 0; + sweepincr = 1; + interval = 1000; + waittime = MAXWAIT; + nrcvtimeout = 0; + tmin = 999999999.0; + tmax = 0.0; + tsum = 0.0; + tsumsq = 0.0; + globals->exit_code = 1; + if (setjmp (globals->exit_jmp) == 0) + return main_ping (argc, argv, globals); + return globals->exit_code; +} +#endif + + + +int +#ifdef __rtems__ +main_ping(argc, argv, globals) +#else +main(argc, argv) +#endif + int argc; + char *const *argv; + rtems_shell_globals_t* globals; +{ + struct sockaddr_in from, sock_in; + struct in_addr ifaddr; + struct timeval last, intvl; + struct iovec iov; + struct ip *ip; + struct msghdr msg; + struct sigaction si_sa; + size_t sz; +#if !__rtems__ + u_char *datap, packet[IP_MAXPACKET] __aligned(4); +#else + u_char *datap; +#endif + char *ep, *source, *target, *payload; + struct hostent *hp; +#ifdef IPSEC_POLICY_IPSEC + char *policy_in, *policy_out; +#endif + struct sockaddr_in *to; + double t; + u_long alarmtimeout, ultmp; + int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno, + tos, ttl; + char ctrl[CMSG_SPACE(sizeof(struct timeval))]; + char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; +#ifdef IP_OPTIONS + char rspace[MAX_IPOPTLEN]; /* record route space */ +#endif + unsigned char loop, mttl; +#ifdef __rtems__ + struct getopt_data getopt_reent; +#define optarg getopt_reent.optarg +#define optind getopt_reent.optind +#define opterr getopt.reent.opterr +#define optopt getopt.reent.optopt +#endif + + payload = source = NULL; +#ifdef IPSEC_POLICY_IPSEC + policy_in = policy_out = NULL; +#endif + + /* + * Do the stuff that we need root priv's for *first*, and + * then drop our setuid bit. Save error reporting for + * after arg parsing. + */ + s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + sockerrno = errno; + + setuid(getuid()); + uid = getuid(); + + alarmtimeout = df = preload = tos = 0; + + outpack = outpackhdr + sizeof(struct ip); +#ifdef __rtems__ + memset(&getopt_reent, 0, sizeof(getopt_data)); + while ((ch = getopt_r(argc, argv, +#else + while ((ch = getopt(argc, argv, +#endif + "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + "P:" +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ +#ifdef __rtems__ + , &getopt_reent +#endif + )) != -1) + { + switch(ch) { + case 'A': + options_ |= F_MISSED; + break; + case 'a': + options_ |= F_AUDIBLE; + break; + case 'c': + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp) + errx(&globals->exit_jmp, EX_USAGE, + "invalid count of packets to transmit: `%s'", + optarg); + npackets = ultmp; + break; + case 'D': + options_ |= F_HDRINCL; + df = 1; + break; + case 'd': + options_ |= F_SO_DEBUG; + break; + case 'f': + if (uid) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, "-f flag"); + } + options_ |= F_FLOOD; + setbuf(stdout, (char *)NULL); + break; + case 'G': /* Maximum packet size for ping sweep */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg) + errx(&globals->exit_jmp, EX_USAGE, "invalid packet size: `%s'", + optarg); + if (uid != 0 && ultmp > DEFDATALEN) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, + "packet size too large: %lu > %u", + ultmp, DEFDATALEN); + } + options_ |= F_SWEEP; + sweepmax = ultmp; + break; + case 'g': /* Minimum packet size for ping sweep */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg) + errx(&globals->exit_jmp, EX_USAGE, "invalid packet size: `%s'", + optarg); + if (uid != 0 && ultmp > DEFDATALEN) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, + "packet size too large: %lu > %u", + ultmp, DEFDATALEN); + } + options_ |= F_SWEEP; + sweepmin = ultmp; + break; + case 'h': /* Packet size increment for ping sweep */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp < 1) + errx(&globals->exit_jmp, EX_USAGE, "invalid increment size: `%s'", + optarg); + if (uid != 0 && ultmp > DEFDATALEN) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, + "packet size too large: %lu > %u", + ultmp, DEFDATALEN); + } + options_ |= F_SWEEP; + sweepincr = ultmp; + break; + case 'I': /* multicast interface */ + if (inet_aton(optarg, &ifaddr) == 0) + errx(&globals->exit_jmp, EX_USAGE, + "invalid multicast interface: `%s'", + optarg); + options_ |= F_MIF; + break; + case 'i': /* wait between sending packets */ + t = strtod(optarg, &ep) * 1000.0; + if (*ep || ep == optarg || t > (double)INT_MAX) + errx(&globals->exit_jmp, EX_USAGE, "invalid timing interval: `%s'", + optarg); + options_ |= F_INTERVAL; + interval = (int)t; + if (uid && interval < 1000) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, "-i interval too short"); + } + break; + case 'L': + options_ |= F_NOLOOP; + loop = 0; + break; + case 'l': + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp > INT_MAX) + errx(&globals->exit_jmp, EX_USAGE, + "invalid preload value: `%s'", optarg); + if (uid) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, "-l flag"); + } + preload = ultmp; + break; + case 'M': + switch(optarg[0]) { + case 'M': + case 'm': + options_ |= F_MASK; + break; + case 'T': + case 't': + options_ |= F_TIME; + break; + default: + errx(&globals->exit_jmp, EX_USAGE, "invalid message: `%c'", optarg[0]); + break; + } + break; + case 'm': /* TTL */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp > MAXTTL) + errx(&globals->exit_jmp, EX_USAGE, "invalid TTL: `%s'", optarg); + ttl = ultmp; + options_ |= F_TTL; + break; + case 'n': + options_ |= F_NUMERIC; + break; + case 'o': + options_ |= F_ONCE; + break; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + case 'P': + options_ |= F_POLICY; + if (!strncmp("in", optarg, 2)) + policy_in = strdup(optarg); + else if (!strncmp("out", optarg, 3)) + policy_out = strdup(optarg); + else + errx(&globals->exit_jmp, 1, "invalid security policy"); + break; +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + case 'p': /* fill buffer with user pattern */ + options_ |= F_PINGFILLED; + payload = optarg; + break; + case 'Q': + options_ |= F_QUIET2; + break; + case 'q': + options_ |= F_QUIET; + break; + case 'R': + options_ |= F_RROUTE; + break; + case 'r': + options_ |= F_SO_DONTROUTE; + break; + case 'S': + source = optarg; + break; + case 's': /* size of packet to send */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg) + errx(&globals->exit_jmp, EX_USAGE, "invalid packet size: `%s'", + optarg); + if (uid != 0 && ultmp > DEFDATALEN) { + errno = EPERM; + err(&globals->exit_jmp, EX_NOPERM, + "packet size too large: %lu > %u", + ultmp, DEFDATALEN); + } + datalen = ultmp; + break; + case 'T': /* multicast TTL */ + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp > MAXTTL) + errx(&globals->exit_jmp, EX_USAGE, "invalid multicast TTL: `%s'", + optarg); + mttl = ultmp; + options_ |= F_MTTL; + break; + case 't': + alarmtimeout = strtoul(optarg, &ep, 0); + if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX)) + errx(&globals->exit_jmp, EX_USAGE, "invalid timeout: `%s'", + optarg); + if (alarmtimeout > MAXALARM) + errx(&globals->exit_jmp, EX_USAGE, "invalid timeout: `%s' > %d", + optarg, MAXALARM); + alarm((int)alarmtimeout); + break; + case 'v': + options_ |= F_VERBOSE; + break; + case 'W': /* wait ms for answer */ + t = strtod(optarg, &ep); + if (*ep || ep == optarg || t > (double)INT_MAX) + errx(&globals->exit_jmp, EX_USAGE, "invalid timing interval: `%s'", + optarg); + options_ |= F_WAITTIME; + waittime = (int)t; + break; + case 'z': + options_ |= F_HDRINCL; + ultmp = strtoul(optarg, &ep, 0); + if (*ep || ep == optarg || ultmp > MAXTOS) + errx(&globals->exit_jmp, EX_USAGE, "invalid TOS: `%s'", optarg); + tos = ultmp; + break; + default: + usage(); + + } + } + + if (argc - optind != 1) + usage(); + + target = argv[optind]; + + switch (options_ & (F_MASK|F_TIME)) { + case 0: break; + case F_MASK: + icmp_type_ = ICMP_MASKREQ; + icmp_type_rsp = ICMP_MASKREPLY; + phdr_len = MASK_LEN; + if (!(options_ & F_QUIET)) + (void)printf("ICMP_MASKREQ\n"); + break; + case F_TIME: + icmp_type_ = ICMP_TSTAMP; + icmp_type_rsp = ICMP_TSTAMPREPLY; + phdr_len = TS_LEN; + if (!(options_ & F_QUIET)) + (void)printf("ICMP_TSTAMP\n"); + break; + default: + errx(&globals->exit_jmp, EX_USAGE, "ICMP_TSTAMP and ICMP_MASKREQ are exclusive."); + break; + } + icmp_len = sizeof(struct ip) + ICMP_MINLEN + phdr_len; + if (options_ & F_RROUTE) + icmp_len += MAX_IPOPTLEN; + maxpayload = IP_MAXPACKET - icmp_len; + if (datalen > maxpayload) + errx(&globals->exit_jmp, EX_USAGE, "packet size too large: %d > %d", datalen, + maxpayload); + send_len = icmp_len + datalen; + datap = &outpack[ICMP_MINLEN + phdr_len + TIMEVAL_LEN]; + if (options_ & F_PINGFILLED) { + fill((char *)datap, payload); + } + if (source) { + bzero((char *)&sock_in, sizeof(sock_in)); + sock_in.sin_family = AF_INET; + if (inet_aton(source, &sock_in.sin_addr) != 0) { + shostname = source; + } else { + hp = gethostbyname2(source, AF_INET); + if (!hp) + errx(&globals->exit_jmp, EX_NOHOST, "cannot resolve %s: %s", + source, hstrerror(h_errno)); + + sock_in.sin_len = sizeof sock_in; + if ((unsigned)hp->h_length > sizeof(sock_in.sin_addr) || + hp->h_length < 0) + errx(&globals->exit_jmp, 1, "gethostbyname2: illegal address"); + memcpy(&sock_in.sin_addr, hp->h_addr_list[0], + sizeof(sock_in.sin_addr)); + (void)strncpy(snamebuf, hp->h_name, + sizeof(snamebuf) - 1); + snamebuf[sizeof(snamebuf) - 1] = '\0'; + shostname = snamebuf; + } + if (bind(s, (struct sockaddr *)&sock_in, sizeof sock_in) == -1) + err(&globals->exit_jmp, 1, "bind"); + } + + bzero(&whereto, sizeof(whereto)); + to = &whereto; + to->sin_family = AF_INET; + to->sin_len = sizeof *to; + if (inet_aton(target, &to->sin_addr) != 0) { + hostname = target; + } else { + hp = gethostbyname2(target, AF_INET); + if (!hp) + errx(&globals->exit_jmp, EX_NOHOST, "cannot resolve %s: %s", + target, hstrerror(h_errno)); + + if ((unsigned)hp->h_length > sizeof(to->sin_addr)) + errx(&globals->exit_jmp, 1, "gethostbyname2 returned an illegal address"); + memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr); + (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); + hnamebuf[sizeof(hnamebuf) - 1] = '\0'; + hostname = hnamebuf; + } + + if (options_ & F_FLOOD && options_ & F_INTERVAL) + errx(&globals->exit_jmp, EX_USAGE, "-f and -i: incompatible options"); + + if (options_ & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr))) + errx(&globals->exit_jmp, EX_USAGE, + "-f flag cannot be used with multicast destination"); + if (options_ & (F_MIF | F_NOLOOP | F_MTTL) + && !IN_MULTICAST(ntohl(to->sin_addr.s_addr))) + errx(&globals->exit_jmp, EX_USAGE, + "-I, -L, -T flags cannot be used with unicast destination"); + + if (datalen >= TIMEVAL_LEN) /* can we time transfer */ + timing = 1; + + if (!(options_ & F_PINGFILLED)) + for (i = TIMEVAL_LEN; i < datalen; ++i) + *datap++ = i; + + ident = getpid() & 0xFFFF; + + if (s < 0) { + errno = sockerrno; + err(&globals->exit_jmp, EX_OSERR, "socket"); + } + hold = 1; + if (options_ & F_SO_DEBUG) + (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, + sizeof(hold)); + if (options_ & F_SO_DONTROUTE) + (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, + sizeof(hold)); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + if (options_ & F_POLICY) { + char *buf; + if (policy_in != NULL) { + buf = ipsec_set_policy(policy_in, strlen(policy_in)); + if (buf == NULL) + errx(&globals->exit_jmp, EX_CONFIG, "%s", ipsec_strerror()); + if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(EX_CONFIG, + "ipsec policy cannot be configured"); + free(buf); + } + + if (policy_out != NULL) { + buf = ipsec_set_policy(policy_out, strlen(policy_out)); + if (buf == NULL) + errx(&globals->exit_jmp, EX_CONFIG, "%s", ipsec_strerror()); + if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(EX_CONFIG, + "ipsec policy cannot be configured"); + free(buf); + } + } +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + + if (options_ & F_HDRINCL) { + ip = (struct ip*)outpackhdr; + if (!(options_ & (F_TTL | F_MTTL))) { + mib[0] = CTL_NET; + mib[1] = PF_INET; + mib[2] = IPPROTO_IP; + mib[3] = IPCTL_DEFTTL; + sz = sizeof(ttl); + if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1) + err(&globals->exit_jmp, 1, "sysctl(net.inet.ip.ttl)"); + } + setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); + ip->ip_v = IPVERSION; + ip->ip_hl = sizeof(struct ip) >> 2; + ip->ip_tos = tos; + ip->ip_id = 0; + ip->ip_off = df ? IP_DF : 0; + ip->ip_ttl = ttl; + ip->ip_p = IPPROTO_ICMP; + ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; + ip->ip_dst = to->sin_addr; + } + /* record route option */ + if (options_ & F_RROUTE) { +#ifdef IP_OPTIONS + bzero(rspace, sizeof(rspace)); + rspace[IPOPT_OPTVAL] = IPOPT_RR; + rspace[IPOPT_OLEN] = sizeof(rspace) - 1; + rspace[IPOPT_OFFSET] = IPOPT_MINOFF; + rspace[sizeof(rspace) - 1] = IPOPT_EOL; + if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, + sizeof(rspace)) < 0) + err(&globals->exit_jmp, EX_OSERR, "setsockopt IP_OPTIONS"); +#else + errx(&globals->exit_jmp, EX_UNAVAILABLE, + "record route not available in this implementation"); +#endif /* IP_OPTIONS */ + } + + if (options_ & F_TTL) { + if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, + sizeof(ttl)) < 0) { + err(&globals->exit_jmp, EX_OSERR, "setsockopt IP_TTL"); + } + } + if (options_ & F_NOLOOP) { + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, + sizeof(loop)) < 0) { + err(&globals->exit_jmp, EX_OSERR, "setsockopt IP_MULTICAST_LOOP"); + } + } + if (options_ & F_MTTL) { + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, + sizeof(mttl)) < 0) { + err(&globals->exit_jmp, EX_OSERR, "setsockopt IP_MULTICAST_TTL"); + } + } + if (options_ & F_MIF) { + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr, + sizeof(ifaddr)) < 0) { + err(&globals->exit_jmp, EX_OSERR, "setsockopt IP_MULTICAST_IF"); + } + } +#ifdef SO_TIMESTAMP + { int on = 1; + if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0) + err(&globals->exit_jmp, EX_OSERR, "setsockopt SO_TIMESTAMP"); + } +#endif + if (sweepmax) { + if (sweepmin >= sweepmax) + errx(&globals->exit_jmp, EX_USAGE, "Maximum packet size must be greater than the minimum packet size"); + + if (datalen != DEFDATALEN) + errx(&globals->exit_jmp, EX_USAGE, "Packet size and ping sweep are mutually exclusive"); + + if (npackets > 0) { + snpackets = npackets; + npackets = 0; + } else + snpackets = 1; + datalen = sweepmin; + send_len = icmp_len + sweepmin; + } + if (options_ & F_SWEEP && !sweepmax) + errx(&globals->exit_jmp, EX_USAGE, "Maximum sweep size must be specified"); + + /* + * When pinging the broadcast address, you can get a lot of answers. + * Doing something so evil is useful if you are trying to stress the + * ethernet, or just want to fill the arp cache to get some stuff for + * /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast + * or multicast pings if they wish. + */ + + /* + * XXX receive buffer needs undetermined space for mbuf overhead + * as well. + */ + hold = IP_MAXPACKET + 128; + (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, + sizeof(hold)); + if (uid == 0) + (void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold, + sizeof(hold)); + + if (to->sin_family == AF_INET) { + (void)printf("PING %s (%s)", hostname, + inet_ntoa(to->sin_addr)); + if (source) + (void)printf(" from %s", shostname); + if (sweepmax) + (void)printf(": (%d ... %d) data bytes\n", + sweepmin, sweepmax); + else + (void)printf(": %d data bytes\n", datalen); + + } else { + if (sweepmax) + (void)printf("PING %s: (%d ... %d) data bytes\n", + hostname, sweepmin, sweepmax); + else + (void)printf("PING %s: %d data bytes\n", hostname, datalen); + } + + /* + * Use sigaction() instead of signal() to get unambiguous semantics, + * in particular with SA_RESTART not set. + */ + + sigemptyset(&si_sa.sa_mask); + si_sa.sa_flags = 0; + + si_sa.sa_handler = stopit; + if (sigaction(SIGINT, &si_sa, 0) == -1) { + err(&globals->exit_jmp, EX_OSERR, "sigaction SIGINT"); + } + +#ifdef SIGINFO + si_sa.sa_handler = status; + if (sigaction(SIGINFO, &si_sa, 0) == -1) { + err(EX_OSERR, "sigaction"); + } +#endif + + if (alarmtimeout > 0) { + si_sa.sa_handler = stopit; + if (sigaction(SIGALRM, &si_sa, 0) == -1) + err(&globals->exit_jmp, EX_OSERR, "sigaction SIGALRM"); + } + + bzero(&msg, sizeof(msg)); + msg.msg_name = (caddr_t)&from; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; +#ifdef SO_TIMESTAMP + msg.msg_control = (caddr_t)ctrl; +#endif + iov.iov_base = packet_; + iov.iov_len = IP_MAXPACKET; + + if (preload == 0) + pinger(); /* send the first ping */ + else { + if (npackets != 0 && preload > npackets) + preload = npackets; + while (preload--) /* fire off them quickies */ + pinger(); + } + (void)gettimeofday(&last, NULL); + + if (options_ & F_FLOOD) { + intvl.tv_sec = 0; + intvl.tv_usec = 10000; + } else { + intvl.tv_sec = interval / 1000; + intvl.tv_usec = interval % 1000 * 1000; + } + + almost_done = 0; + while (!finish_up) { + struct timeval now, timeout; + fd_set rfds; + int cc, n; + + check_status(); + if ((unsigned)s >= FD_SETSIZE) + errx(&globals->exit_jmp, EX_OSERR, "descriptor too large"); + FD_ZERO(&rfds); + FD_SET(s, &rfds); + (void)gettimeofday(&now, NULL); + timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; + timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; + while (timeout.tv_usec < 0) { + timeout.tv_usec += 1000000; + timeout.tv_sec--; + } + while (timeout.tv_usec >= 1000000) { + timeout.tv_usec -= 1000000; + timeout.tv_sec++; + } + if (timeout.tv_sec < 0) + timeout.tv_sec = timeout.tv_usec = 0; + n = select(s + 1, &rfds, NULL, NULL, &timeout); + if (n < 0) + continue; /* Must be EINTR. */ + if (n == 1) { + struct timeval *tv = NULL; +#ifdef SO_TIMESTAMP + struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl; + + msg.msg_controllen = sizeof(ctrl); +#endif + + bzero(&msg, sizeof(msg)); + msg.msg_name = (caddr_t)&from; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; +#ifdef SO_TIMESTAMP + msg.msg_control = (caddr_t)ctrl; +#endif + iov.iov_base = packet_; + iov.iov_len = IP_MAXPACKET; + + msg.msg_namelen = sizeof(from); + if ((cc = recvmsg(s, &msg, 0)) < 0) { + if (errno == EINTR) + continue; + warn("recvmsg"); + continue; + } +#ifdef SO_TIMESTAMP + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) { + /* Copy to avoid alignment problems: */ + memcpy(&now, CMSG_DATA(cmsg), sizeof(now)); + tv = &now; + } +#endif + if (tv == NULL) { + (void)gettimeofday(&now, NULL); + tv = &now; + } + pr_pack((char *)packet_, cc, &from, tv); + if ((options_ & F_ONCE && nreceived) || + (npackets && nreceived >= npackets)) + break; + } + if (n == 0 || options_ & F_FLOOD) { + if (sweepmax && sntransmitted == snpackets) { + for (i = 0; i < sweepincr ; ++i) + *datap++ = i; + datalen += sweepincr; + if (datalen > sweepmax) + break; + send_len = icmp_len + datalen; + sntransmitted = 0; + } + if (!npackets || ntransmitted < npackets) + pinger(); + else { + if (almost_done) + break; + almost_done = 1; + intvl.tv_usec = 0; + if (nreceived) { + intvl.tv_sec = 2 * tmax / 1000; + if (!intvl.tv_sec) + intvl.tv_sec = 1; + } else { + intvl.tv_sec = waittime / 1000; + intvl.tv_usec = waittime % 1000 * 1000; + } + } + (void)gettimeofday(&last, NULL); + if (ntransmitted - nreceived - 1 > nmissedmax) { + nmissedmax = ntransmitted - nreceived - 1; + if (options_ & F_MISSED) + (void)write(STDOUT_FILENO, &BBELL, 1); + } + } + } + finish(); +#ifdef __rtems__ + /* RTEMS shell programs return -- they do not exit */ + if (nreceived) + return(0); + else + return(2); +#endif + /* NOTREACHED */ + exit(0); /* Make the compiler happy */ +} + +/* + * stopit -- + * Set the global bit that causes the main loop to quit. + * Do NOT call finish() from here, since finish() does far too much + * to be called from a signal handler. + */ +void +stopit(sig) + int sig __unused; +{ +#if !__rtems__ + /* + * When doing reverse DNS lookups, the finish_up flag might not + * be noticed for a while. Just exit if we get a second SIGINT. + */ + if (!(options_ & F_NUMERIC) && finish_up) + _exit(nreceived ? 0 : 2); + finish_up = 1; +#endif +} + +/* + * pinger -- + * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an ascending integer. The first TIMEVAL_LEN + * bytes of the data portion are used to hold a UNIX "timeval" struct in + * host byte-order, to compute the round-trip time. + */ +static void +g_pinger(globals) + rtems_shell_globals_t* globals; +{ + struct timeval now; + struct tv32 tv32; + struct ip *ip; + struct icmp *icp; + int cc, i; + u_char *packet; + + packet = outpack; + icp = (struct icmp *)outpack; + icp->icmp_type = icmp_type_; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = htons(ntransmitted); + icp->icmp_id = ident; /* ID */ + + CLR(ntransmitted % mx_dup_ck); + + if ((options_ & F_TIME) || timing) { + (void)gettimeofday(&now, NULL); + + tv32.tv32_sec = htonl(now.tv_sec); + tv32.tv32_usec = htonl(now.tv_usec); + if (options_ & F_TIME) + icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) + * 1000 + now.tv_usec / 1000); + if (timing) + bcopy((void *)&tv32, + (void *)&outpack[ICMP_MINLEN + phdr_len], + sizeof(tv32)); + } + + cc = ICMP_MINLEN + phdr_len + datalen; + + /* compute ICMP checksum here */ + icp->icmp_cksum = in_cksum((u_short *)icp, cc); + + if (options_ & F_HDRINCL) { + cc += sizeof(struct ip); + ip = (struct ip *)outpackhdr; + ip->ip_len = cc; + ip->ip_sum = in_cksum((u_short *)outpackhdr, cc); + packet = outpackhdr; + } + i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto, + sizeof(whereto)); + + if (i < 0 || i != cc) { + if (i < 0) { + if (options_ & F_FLOOD && errno == ENOBUFS) { + usleep(FLOOD_BACKOFF); + return; + } + warn("sendto"); + } else { + warn("%s: partial write: %d of %d bytes", + hostname, i, cc); + } + } + ntransmitted++; + sntransmitted++; + if (!(options_ & F_QUIET) && options_ & F_FLOOD) + (void)write(STDOUT_FILENO, &DOT, 1); +} + +/* + * pr_pack -- + * Print out the packet, if it came from us. This logic is necessary + * because ALL readers of the ICMP socket get a copy of ALL ICMP packets + * which arrive ('tis only fair). This permits multiple copies of this + * program to be run without having intermingled output (or statistics!). + */ +static void +g_pr_pack(buf, cc, from, tv, globals) + char *buf; + int cc; + struct sockaddr_in *from; + struct timeval *tv; + rtems_shell_globals_t* globals; +{ + struct in_addr ina; + u_char *cp, *dp; + struct icmp *icp; + struct ip *ip; + const void *tp; + double triptime; + int dupflag, hlen, i, j, recv_len, seq; +#if !__rtems__ + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; +#endif + + /* Check the IP header */ + ip = (struct ip *)buf; + hlen = ip->ip_hl << 2; + recv_len = cc; + if (cc < hlen + ICMP_MINLEN) { + if (options_ & F_VERBOSE) + warn("packet too short (%d bytes) from %s", cc, + inet_ntoa(from->sin_addr)); + return; + } + + /* Now the ICMP part */ + cc -= hlen; + icp = (struct icmp *)(buf + hlen); + if (icp->icmp_type == icmp_type_rsp) { + if (icp->icmp_id != ident) + return; /* 'Twas not our ECHO */ + ++nreceived; + triptime = 0.0; + if (timing) { + struct timeval tv1; + struct tv32 tv32; +#ifndef icmp_data + tp = &icp->icmp_ip; +#else + tp = icp->icmp_data; +#endif + tp = (const char *)tp + phdr_len; + + if (cc - ICMP_MINLEN - phdr_len >= (int) sizeof(tv1)) { + /* Copy to avoid alignment problems: */ + memcpy(&tv32, tp, sizeof(tv32)); + tv1.tv_sec = ntohl(tv32.tv32_sec); + tv1.tv_usec = ntohl(tv32.tv32_usec); + tvsub(tv, &tv1); + triptime = ((double)tv->tv_sec) * 1000.0 + + ((double)tv->tv_usec) / 1000.0; + tsum += triptime; + tsumsq += triptime * triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } else + timing = 0; + } + + seq = ntohs(icp->icmp_seq); + + if (TST(seq % mx_dup_ck)) { + ++nrepeats; + --nreceived; + dupflag = 1; + } else { + SET(seq % mx_dup_ck); + dupflag = 0; + } + + if (options_ & F_QUIET) + return; + + if (options_ & F_WAITTIME && triptime > waittime) { + ++nrcvtimeout; + return; + } + + if (options_ & F_FLOOD) + (void)write(STDOUT_FILENO, &BSPACE, 1); + else { + (void)printf("%d bytes from %s: icmp_seq=%u", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), + seq); + (void)printf(" ttl=%d", ip->ip_ttl); + if (timing) + (void)printf(" time=%.3f ms", triptime); + if (dupflag) + (void)printf(" (DUP!)"); + if (options_ & F_AUDIBLE) + (void)write(STDOUT_FILENO, &BBELL, 1); + if (options_ & F_MASK) { + /* Just prentend this cast isn't ugly */ + (void)printf(" mask=%s", + pr_addr(*(struct in_addr *)&(icp->icmp_mask))); + } + if (options_ & F_TIME) { + (void)printf(" tso=%s", pr_ntime(icp->icmp_otime)); + (void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime)); + (void)printf(" tst=%s", pr_ntime(icp->icmp_ttime)); + } + if (recv_len != send_len) { + (void)printf( + "\nwrong total length %d instead of %d", + recv_len, send_len); + } + /* check the data */ + cp = (u_char*)&icp->icmp_data[phdr_len]; + dp = &outpack[ICMP_MINLEN + phdr_len]; + cc -= ICMP_MINLEN + phdr_len; + i = 0; + if (timing) { /* don't check variable timestamp */ + cp += TIMEVAL_LEN; + dp += TIMEVAL_LEN; + cc -= TIMEVAL_LEN; + i += TIMEVAL_LEN; + } + for (; i < datalen && cc > 0; ++i, ++cp, ++dp, --cc) { + if (*cp != *dp) { + (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", + i, *dp, *cp); + (void)printf("\ncp:"); + cp = (u_char*)&icp->icmp_data[0]; + for (i = 0; i < datalen; ++i, ++cp) { + if ((i % 16) == 8) + (void)printf("\n\t"); + (void)printf("%2x ", *cp); + } + (void)printf("\ndp:"); + cp = &outpack[ICMP_MINLEN]; + for (i = 0; i < datalen; ++i, ++cp) { + if ((i % 16) == 8) + (void)printf("\n\t"); + (void)printf("%2x ", *cp); + } + break; + } + } + } + } else { + /* + * We've got something other than an ECHOREPLY. + * See if it's a reply to something that we sent. + * We can compare IP destination, protocol, + * and ICMP type and ID. + * + * Only print all the error messages if we are running + * as root to avoid leaking information not normally + * available to those not running as root. + */ +#ifndef icmp_data + struct ip *oip = &icp->icmp_ip; +#else + struct ip *oip = (struct ip *)icp->icmp_data; +#endif + struct icmp *oicmp = (struct icmp *)(oip + 1); + + if (((options_ & F_VERBOSE) && uid == 0) || + (!(options_ & F_QUIET2) && + (oip->ip_dst.s_addr == whereto.sin_addr.s_addr) && + (oip->ip_p == IPPROTO_ICMP) && + (oicmp->icmp_type == ICMP_ECHO) && + (oicmp->icmp_id == ident))) { + (void)printf("%d bytes from %s: ", cc, + pr_addr(from->sin_addr)); + pr_icmph(icp); + } else + return; + } + + /* Display any IP options */ + cp = (u_char *)buf + sizeof(struct ip); + + for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + case IPOPT_SSRR: + (void)printf(*cp == IPOPT_LSRR ? + "\nLSRR: " : "\nSSRR: "); + j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1; + hlen -= 2; + cp += 2; + if (j >= INADDR_LEN && + j <= hlen - (int)sizeof(struct ip)) { + for (;;) { + bcopy(++cp, &ina.s_addr, INADDR_LEN); + if (ina.s_addr == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", + pr_addr(ina)); + hlen -= INADDR_LEN; + cp += INADDR_LEN - 1; + j -= INADDR_LEN; + if (j < INADDR_LEN) + break; + (void)putchar('\n'); + } + } else + (void)printf("\t(truncated route)\n"); + break; + case IPOPT_RR: + j = cp[IPOPT_OLEN]; /* get length */ + i = cp[IPOPT_OFFSET]; /* and pointer */ + hlen -= 2; + cp += 2; + if (i > j) + i = j; + i = i - IPOPT_MINOFF + 1; + if (i < 0 || i > (hlen - (int)sizeof(struct ip))) { + old_rrlen = 0; + continue; + } + if (i == old_rrlen + && !bcmp((char *)cp, old_rr, i) + && !(options_ & F_FLOOD)) { + (void)printf("\t(same route)"); + hlen -= i; + cp += i; + break; + } + old_rrlen = i; + bcopy((char *)cp, old_rr, i); + (void)printf("\nRR: "); + if (i >= INADDR_LEN && + i <= hlen - (int)sizeof(struct ip)) { + for (;;) { + bcopy(++cp, &ina.s_addr, INADDR_LEN); + if (ina.s_addr == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", + pr_addr(ina)); + hlen -= INADDR_LEN; + cp += INADDR_LEN - 1; + i -= INADDR_LEN; + if (i < INADDR_LEN) + break; + (void)putchar('\n'); + } + } else + (void)printf("\t(truncated route)"); + break; + case IPOPT_NOP: + (void)printf("\nNOP"); + break; + default: + (void)printf("\nunknown option %x", *cp); + break; + } + if (!(options_ & F_FLOOD)) { + (void)putchar('\n'); + (void)fflush(stdout); + } +} + +/* + * in_cksum -- + * Checksum routine for Internet Protocol family headers (C Version) + */ +u_short +in_cksum(addr, len) + u_short *addr; + int len; +{ + int nleft, sum; + u_short *w; + union { + u_short us; + u_char uc[2]; + } last; + u_short answer; + + nleft = len; + sum = 0; + w = addr; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + last.uc[0] = *(u_char *)w; + last.uc[1] = 0; + sum += last.us; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return(answer); +} + +/* + * tvsub -- + * Subtract 2 timeval structs: out = out - in. Out is assumed to + * be >= in. + */ +static void +tvsub(out, in) + struct timeval *out, *in; +{ + + if ((out->tv_usec -= in->tv_usec) < 0) { + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +/* + * status -- + * Print out statistics when SIGINFO is received. + */ + +#if !defined(__rtems__) +static void +status(sig) + int sig __unused; +{ + siginfo_p = 1; +} +#endif + +static void +g_check_status(globals) + rtems_shell_globals_t* globals; +{ + if (siginfo_p) { + siginfo_p = 0; + (void)fprintf(stderr, "\r%ld/%ld packets received (%.1f%%)", + nreceived, ntransmitted, + ntransmitted ? nreceived * 100.0 / ntransmitted : 0.0); + if (nreceived && timing) + (void)fprintf(stderr, " %.3f min / %.3f avg / %.3f max", + tmin, tsum / (nreceived + nrepeats), tmax); + (void)fprintf(stderr, "\n"); + } +} + +/* + * finish -- + * Print out statistics, and give up. + */ +static void +g_finish(globals) + rtems_shell_globals_t* globals; +{ + + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGALRM, SIG_IGN); + (void)putchar('\n'); + (void)fflush(stdout); + (void)printf("--- %s ping statistics ---\n", hostname); + (void)printf("%ld packets transmitted, ", ntransmitted); + (void)printf("%ld packets received, ", nreceived); + if (nrepeats) + (void)printf("+%ld duplicates, ", nrepeats); + if (ntransmitted) { + if (nreceived > ntransmitted) + (void)printf("-- somebody's printing up packets!"); + else + (void)printf("%.1f%% packet loss", + ((ntransmitted - nreceived) * 100.0) / + ntransmitted); + } + if (nrcvtimeout) + (void)printf(", %ld packets out of wait time", nrcvtimeout); + (void)putchar('\n'); + if (nreceived && timing) { + double n = nreceived + nrepeats; + double avg = tsum / n; +#if defined(__rtems__) + (void) printf( + "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f ms\n", + tmin, avg, tmax); +#else + double vari = tsumsq / n - avg * avg; + (void)printf( + "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n", + tmin, avg, tmax, sqrt(vari)); +#endif + } + if (nreceived) + exit(0); + else + exit(2); + while (1); +} + +#ifdef notdef +static char *ttab[] = { + "Echo Reply", /* ip + seq + udata */ + "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ + "Source Quench", /* IP */ + "Redirect", /* redirect type, gateway, + IP */ + "Echo", + "Time Exceeded", /* transit, frag reassem + IP */ + "Parameter Problem", /* pointer + IP */ + "Timestamp", /* id + seq + three timestamps */ + "Timestamp Reply", /* " */ + "Info Request", /* id + sq */ + "Info Reply" /* " */ +}; +#endif + +/* + * pr_icmph -- + * Print a descriptive string about an ICMP header. + */ +static void +pr_icmph(icp) + struct icmp *icp; +{ + + switch(icp->icmp_type) { + case ICMP_ECHOREPLY: + (void)printf("Echo Reply\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_UNREACH: + switch(icp->icmp_code) { + case ICMP_UNREACH_NET: + (void)printf("Destination Net Unreachable\n"); + break; + case ICMP_UNREACH_HOST: + (void)printf("Destination Host Unreachable\n"); + break; + case ICMP_UNREACH_PROTOCOL: + (void)printf("Destination Protocol Unreachable\n"); + break; + case ICMP_UNREACH_PORT: + (void)printf("Destination Port Unreachable\n"); + break; + case ICMP_UNREACH_NEEDFRAG: + (void)printf("frag needed and DF set (MTU %d)\n", + ntohs(icp->icmp_nextmtu)); + break; + case ICMP_UNREACH_SRCFAIL: + (void)printf("Source Route Failed\n"); + break; + case ICMP_UNREACH_FILTER_PROHIB: + (void)printf("Communication prohibited by filter\n"); + break; + default: + (void)printf("Dest Unreachable, Bad Code: %d\n", + icp->icmp_code); + break; + } + /* Print returned IP header information */ +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_SOURCEQUENCH: + (void)printf("Source Quench\n"); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_REDIRECT: + switch(icp->icmp_code) { + case ICMP_REDIRECT_NET: + (void)printf("Redirect Network"); + break; + case ICMP_REDIRECT_HOST: + (void)printf("Redirect Host"); + break; + case ICMP_REDIRECT_TOSNET: + (void)printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIRECT_TOSHOST: + (void)printf("Redirect Type of Service and Host"); + break; + default: + (void)printf("Redirect, Bad Code: %d", icp->icmp_code); + break; + } + (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_ECHO: + (void)printf("Echo Request\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_TIMXCEED: + switch(icp->icmp_code) { + case ICMP_TIMXCEED_INTRANS: + (void)printf("Time to live exceeded\n"); + break; + case ICMP_TIMXCEED_REASS: + (void)printf("Frag reassembly time exceeded\n"); + break; + default: + (void)printf("Time exceeded, Bad Code: %d\n", + icp->icmp_code); + break; + } +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_PARAMPROB: + (void)printf("Parameter problem: pointer = 0x%02x\n", + icp->icmp_hun.ih_pptr); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_TSTAMP: + (void)printf("Timestamp\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_TSTAMPREPLY: + (void)printf("Timestamp Reply\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_IREQ: + (void)printf("Information Request\n"); + /* XXX ID + Seq */ + break; + case ICMP_IREQREPLY: + (void)printf("Information Reply\n"); + /* XXX ID + Seq */ + break; + case ICMP_MASKREQ: + (void)printf("Address Mask Request\n"); + break; + case ICMP_MASKREPLY: + (void)printf("Address Mask Reply\n"); + break; + case ICMP_ROUTERADVERT: + (void)printf("Router Advertisement\n"); + break; + case ICMP_ROUTERSOLICIT: + (void)printf("Router Solicitation\n"); + break; + default: + (void)printf("Bad ICMP type: %d\n", icp->icmp_type); + } +} + +/* + * pr_iph -- + * Print an IP header with options. + */ +static void +pr_iph(ip) + struct ip *ip; +{ + u_char *cp; + int hlen; + + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + 20; /* point to options */ + + (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n"); + (void)printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len), + ntohs(ip->ip_id)); + (void)printf(" %1lx %04lx", + (u_long) (ntohl(ip->ip_off) & 0xe000) >> 13, + (u_long) ntohl(ip->ip_off) & 0x1fff); + (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, + ntohs(ip->ip_sum)); + (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); + (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); + /* dump any option bytes */ + while (hlen-- > 20) { + (void)printf("%02x", *cp++); + } + (void)putchar('\n'); +} + +/* + * pr_addr -- + * Return an ascii host address as a dotted quad and optionally with + * a hostname. + */ +static char * +g_pr_addr(ina, globals) + struct in_addr ina; + rtems_shell_globals_t* globals; +{ + struct hostent *hp; + static char buf[16 + 3 + MAXHOSTNAMELEN]; + + if ((options_ & F_NUMERIC) || + !(hp = gethostbyaddr((char *)&ina, 4, AF_INET))) + return inet_ntoa(ina); + else + (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, + inet_ntoa(ina)); + return(buf); +} + +/* + * pr_retip -- + * Dump some info on a returned (via ICMP) IP packet. + */ +static void +pr_retip(ip) + struct ip *ip; +{ + u_char *cp; + int hlen; + + pr_iph(ip); + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + hlen; + + if (ip->ip_p == 6) + (void)printf("TCP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + else if (ip->ip_p == 17) + (void)printf("UDP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); +} + +static char * +pr_ntime (n_time timestamp) +{ + static char buf[10]; + int hour, min, sec; + + sec = ntohl(timestamp) / 1000; + hour = sec / 60 / 60; + min = (sec % (60 * 60)) / 60; + sec = (sec % (60 * 60)) % 60; + + (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d", hour, min, sec); + + return (buf); +} + +static void +g_fill(bp, patp, globals) + char *bp, *patp; + rtems_shell_globals_t* globals; +{ + char *cp; + int pat[16]; + u_int ii, jj, kk; + + for (cp = patp; *cp; cp++) { + if (!isxdigit((int)*cp)) + errx(&globals->exit_jmp, EX_USAGE, + "patterns must be specified as hex digits"); + + } + ii = sscanf(patp, + "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", + &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], + &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], + &pat[13], &pat[14], &pat[15]); + + if (ii > 0) + for (kk = 0; kk <= maxpayload - (TIMEVAL_LEN + ii); kk += ii) + for (jj = 0; jj < ii; ++jj) + bp[jj + kk] = pat[jj]; + if (!(options_ & F_QUIET)) { + (void)printf("PATTERN: 0x"); + for (jj = 0; jj < ii; ++jj) + (void)printf("%02x", bp[jj] & 0xFF); + (void)printf("\n"); + } +} + +#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) +#define SECOPT " [-P policy]" +#else +#define SECOPT "" +#endif +static void +g_usage(globals) + rtems_shell_globals_t* globals; +{ + (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", +"usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]", +" [-h sweepincrsize] [-i wait] [-l preload] [-M mask | time] [-m ttl]", +" " SECOPT " [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]", +" [-W waittime] [-z tos] host", +" ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]", +" [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]", +" [-s packetsize] [-T ttl] [-t timeout] [-W waittime]", +" [-z tos] mcast-group"); + exit(EX_USAGE); + while (1); +} + +#if __rtems__ + rtems_shell_cmd_t rtems_shell_PING_Command = { + "ping", /* name */ + "ping [args]", /* usage */ + "network", /* topic */ + rtems_shell_main_ping, /* command */ + NULL, /* alias */ + NULL /* next */ + }; +#endif diff --git a/libmisc/main_route.c b/libmisc/main_route.c new file mode 100644 index 0000000..3b322ca --- /dev/null +++ b/libmisc/main_route.c @@ -0,0 +1,151 @@ +/* + * ROUTE Command Implmentation + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "internal.h" + +static int rtems_shell_main_route( + int argc, + char *argv[] +) +{ + int cmd; + struct sockaddr_in dst; + struct sockaddr_in gw; + struct sockaddr_in netmask; + int f_host; + int f_gw = 0; + int cur_idx; + int flags; + int rc; + + memset(&dst, 0, sizeof(dst)); + memset(&gw, 0, sizeof(gw)); + memset(&netmask, 0, sizeof(netmask)); + + dst.sin_len = sizeof(dst); + dst.sin_family = AF_INET; + dst.sin_addr.s_addr = inet_addr("0.0.0.0"); + + gw.sin_len = sizeof(gw); + gw.sin_family = AF_INET; + gw.sin_addr.s_addr = inet_addr("0.0.0.0"); + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + netmask.sin_addr.s_addr = inet_addr("255.255.255.0"); + + if (argc < 2) { + rtems_bsdnet_show_inet_routes(); + return 0; + } + + if (strcmp(argv[1], "add") == 0) { + cmd = RTM_ADD; + } else if (strcmp(argv[1], "del") == 0) { + cmd = RTM_DELETE; + } else { + printf("invalid command: %s\n", argv[1]); + printf("\tit should be 'add' or 'del'\n"); + return -1; + } + + if (argc < 3) { + printf("not enough arguments\n"); + return -1; + } + + if (strcmp(argv[2], "-host") == 0) { + f_host = 1; + } else if (strcmp(argv[2], "-net") == 0) { + f_host = 0; + } else { + printf("Invalid type: %s\n", argv[1]); + printf("\tit should be '-host' or '-net'\n"); + return -1; + } + + if (argc < 4) { + printf("not enough arguments\n"); + return -1; + } + + inet_pton(AF_INET, argv[3], &dst.sin_addr); + + cur_idx = 4; + while(cur_idx < argc) { + if (strcmp(argv[cur_idx], "gw") == 0) { + if ((cur_idx +1) >= argc) { + printf("no gateway address\n"); + return -1; + } + f_gw = 1; + inet_pton(AF_INET, argv[cur_idx + 1], &gw.sin_addr); + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "netmask") == 0) { + if ((cur_idx +1) >= argc) { + printf("no netmask address\n"); + return -1; + } + f_gw = 1; + inet_pton(AF_INET, argv[cur_idx + 1], &netmask.sin_addr); + cur_idx += 1; + } else { + printf("Unknown argument\n"); + return -1; + } + cur_idx += 1; + } + + flags = RTF_STATIC; + if (f_gw != 0) { + flags |= RTF_GATEWAY; + } + if (f_host != 0) { + flags |= RTF_HOST; + } + + rc = rtems_bsdnet_rtrequest( + cmd, + (struct sockaddr *)&dst, + (struct sockaddr *)&gw, + (struct sockaddr *)&netmask, + flags, + NULL + ); + if (rc < 0) { + printf("Error adding route\n"); + } + + return 0; +} + +rtems_shell_cmd_t rtems_shell_ROUTE_Command = { + "route", /* name */ + "TBD", /* usage */ + "network", /* topic */ + rtems_shell_main_route, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/libmisc/mon-network.c b/libmisc/mon-network.c new file mode 100644 index 0000000..2140044 --- /dev/null +++ b/libmisc/mon-network.c @@ -0,0 +1,342 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +void mon_ifconfig(int argc, char *argv[], + uint32_t command_arg RTEMS_UNUSED, + bool verbose RTEMS_UNUSED) +{ + struct sockaddr_in ipaddr; + struct sockaddr_in dstaddr; + struct sockaddr_in netmask; + struct sockaddr_in broadcast; + char *iface; + int f_ip = 0; + int f_ptp = 0; + int f_netmask = 0; + int f_up = 0; + int f_down = 0; + int f_bcast = 0; + int cur_idx; + int rc; + int flags; + + memset(&ipaddr, 0, sizeof(ipaddr)); + memset(&dstaddr, 0, sizeof(dstaddr)); + memset(&netmask, 0, sizeof(netmask)); + memset(&broadcast, 0, sizeof(broadcast)); + + ipaddr.sin_len = sizeof(ipaddr); + ipaddr.sin_family = AF_INET; + + dstaddr.sin_len = sizeof(dstaddr); + dstaddr.sin_family = AF_INET; + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + + broadcast.sin_len = sizeof(broadcast); + broadcast.sin_family = AF_INET; + + cur_idx = 0; + if (argc <= 1) { + /* display all interfaces */ + iface = NULL; + cur_idx += 1; + } else { + iface = argv[1]; + if (isdigit((unsigned char)*argv[2])) { + if (inet_pton(AF_INET, argv[2], &ipaddr.sin_addr) < 0) { + printf("bad ip address: %s\n", argv[2]); + return; + } + f_ip = 1; + cur_idx += 3; + } else { + cur_idx += 2; + } + } + + if ((f_down !=0) && (f_ip != 0)) { + f_up = 1; + } + + while(argc > cur_idx) { + if (strcmp(argv[cur_idx], "up") == 0) { + f_up = 1; + if (f_down != 0) { + printf("Can't make interface up and down\n"); + } + } else if(strcmp(argv[cur_idx], "down") == 0) { + f_down = 1; + if (f_up != 0) { + printf("Can't make interface up and down\n"); + } + } else if(strcmp(argv[cur_idx], "netmask") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No netmask address\n"); + return; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &netmask.sin_addr) < 0) { + printf("bad netmask: %s\n", argv[cur_idx]); + return; + } + f_netmask = 1; + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "broadcast") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No broadcast address\n"); + return; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &broadcast.sin_addr) < 0) { + printf("bad broadcast: %s\n", argv[cur_idx]); + return; + } + f_bcast = 1; + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "pointopoint") == 0) { + if ((cur_idx + 1) >= argc) { + printf("No pointopoint address\n"); + return; + } + if (inet_pton(AF_INET, argv[cur_idx+1], &dstaddr.sin_addr) < 0) { + printf("bad pointopoint: %s\n", argv[cur_idx]); + return; + } + + f_ptp = 1; + cur_idx += 1; + } else { + printf("Bad parameter: %s\n", argv[cur_idx]); + return; + } + + cur_idx += 1; + } + + printf("ifconfig "); + if (iface != NULL) { + printf("%s ", iface); + if (f_ip != 0) { + char str[256]; + inet_ntop(AF_INET, &ipaddr.sin_addr, str, 256); + printf("%s ", str); + } + + if (f_netmask != 0) { + char str[256]; + inet_ntop(AF_INET, &netmask.sin_addr, str, 256); + printf("netmask %s ", str); + } + + if (f_bcast != 0) { + char str[256]; + inet_ntop(AF_INET, &broadcast.sin_addr, str, 256); + printf("broadcast %s ", str); + } + + if (f_ptp != 0) { + char str[256]; + inet_ntop(AF_INET, &dstaddr.sin_addr, str, 256); + printf("pointopoint %s ", str); + } + + if (f_up != 0) { + printf("up\n"); + } else if (f_down != 0) { + printf("down\n"); + } else { + printf("\n"); + } + } + + if ((iface == NULL) || ((f_ip == 0) && (f_down == 0) && (f_up == 0))) { + rtems_bsdnet_show_if_stats(); + return; + } + + flags = 0; + if (f_netmask) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFNETMASK, &netmask); + if (rc < 0) { + printf("Could not set netmask: %s\n", strerror(errno)); + return; + } + } + + if (f_bcast) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFBRDADDR, &broadcast); + if (rc < 0) { + printf("Could not set broadcast: %s\n", strerror(errno)); + return; + } + } + + if (f_ptp) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFDSTADDR, &dstaddr); + if (rc < 0) { + printf("Could not set destination address: %s\n", strerror(errno)); + return; + } + flags |= IFF_POINTOPOINT; + } + + /* This must come _after_ setting the netmask, broadcast addresses */ + if (f_ip) { + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFADDR, &ipaddr); + if (rc < 0) { + printf("Could not set IP address: %s\n", strerror(errno)); + return; + } + } + + if (f_up != 0) { + flags |= IFF_UP; + } + + if (f_down != 0) { + printf("Warning: taking interfaces down is not supported\n"); + } + + rc = rtems_bsdnet_ifconfig(iface, SIOCSIFFLAGS, &flags); + if (rc < 0) { + printf("Could not set interface flags: %s\n", strerror(errno)); + return; + } +} + + + +void mon_route(int argc, char *argv[], + uint32_t command_arg RTEMS_UNUSED, + bool verbose RTEMS_UNUSED) +{ + int cmd; + struct sockaddr_in dst; + struct sockaddr_in gw; + struct sockaddr_in netmask; + int f_host; + int f_gw = 0; + int cur_idx; + int flags; + int rc; + + memset(&dst, 0, sizeof(dst)); + memset(&gw, 0, sizeof(gw)); + memset(&netmask, 0, sizeof(netmask)); + + dst.sin_len = sizeof(dst); + dst.sin_family = AF_INET; + dst.sin_addr.s_addr = inet_addr("0.0.0.0"); + + gw.sin_len = sizeof(gw); + gw.sin_family = AF_INET; + gw.sin_addr.s_addr = inet_addr("0.0.0.0"); + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + netmask.sin_addr.s_addr = inet_addr("255.255.255.0"); + + if (argc < 2) { + rtems_bsdnet_show_inet_routes(); + return; + } + + if (strcmp(argv[1], "add") == 0) { + cmd = RTM_ADD; + } else if (strcmp(argv[1], "del") == 0) { + cmd = RTM_DELETE; + } else { + printf("invalid command: %s\n", argv[1]); + printf("\tit should be 'add' or 'del'\n"); + return; + } + + if (argc < 3) { + printf("not enough arguments\n"); + return; + } + + if (strcmp(argv[2], "-host") == 0) { + f_host = 1; + } else if (strcmp(argv[2], "-net") == 0) { + f_host = 0; + } else { + printf("Invalid type: %s\n", argv[1]); + printf("\tit should be '-host' or '-net'\n"); + return; + } + + if (argc < 4) { + printf("not enough arguments\n"); + return; + } + + inet_pton(AF_INET, argv[3], &dst.sin_addr); + + cur_idx = 4; + while(cur_idx < argc) { + if (strcmp(argv[cur_idx], "gw") == 0) { + if ((cur_idx +1) >= argc) { + printf("no gateway address\n"); + return; + } + f_gw = 1; + inet_pton(AF_INET, argv[cur_idx + 1], &gw.sin_addr); + cur_idx += 1; + } else if(strcmp(argv[cur_idx], "netmask") == 0) { + if ((cur_idx +1) >= argc) { + printf("no netmask address\n"); + return; + } + f_gw = 1; + inet_pton(AF_INET, argv[cur_idx + 1], &netmask.sin_addr); + cur_idx += 1; + } else { + printf("Unknown argument: %s\n", argv[cur_idx]); + return; + } + cur_idx += 1; + } + + flags = RTF_STATIC; + if (f_gw != 0) { + flags |= RTF_GATEWAY; + } + if (f_host != 0) { + flags |= RTF_HOST; + } + + rc = rtems_bsdnet_rtrequest(cmd, + (struct sockaddr*) &dst, + (struct sockaddr*) &gw, + (struct sockaddr*) &netmask, flags, NULL); + if (rc < 0) { + printf("Error adding route\n"); + } +} diff --git a/libmisc/sysexits.h b/libmisc/sysexits.h new file mode 100644 index 0000000..50827f1 --- /dev/null +++ b/libmisc/sysexits.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1987, 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. 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. + * + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + * + * $FreeBSD: release/9.1.0/include/sysexits.h 203964 2010-02-16 19:39:50Z imp $ + */ + +#ifndef _SYSEXITS_H_ +#define _SYSEXITS_H_ + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* !_SYSEXITS_H_ */ diff --git a/librpc/README_RTEMS b/librpc/README_RTEMS new file mode 100644 index 0000000..e60f879 --- /dev/null +++ b/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/librpc/include/rpcsvc/bootparam_prot.x b/librpc/include/rpcsvc/bootparam_prot.x new file mode 100644 index 0000000..0f74c8f --- /dev/null +++ b/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/librpc/include/rpcsvc/crypt.x b/librpc/include/rpcsvc/crypt.x new file mode 100644 index 0000000..8df1654 --- /dev/null +++ b/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/librpc/include/rpcsvc/key_prot.x b/librpc/include/rpcsvc/key_prot.x new file mode 100644 index 0000000..f545569 --- /dev/null +++ b/librpc/include/rpcsvc/key_prot.x @@ -0,0 +1,282 @@ +%/* +% * 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/librpc/include/rpcsvc/klm_prot.x b/librpc/include/rpcsvc/klm_prot.x new file mode 100644 index 0000000..c4cfe36 --- /dev/null +++ b/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/librpc/include/rpcsvc/mount.x b/librpc/include/rpcsvc/mount.x new file mode 100644 index 0000000..f68a06f --- /dev/null +++ b/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/librpc/include/rpcsvc/nfs_prot.x b/librpc/include/rpcsvc/nfs_prot.x new file mode 100644 index 0000000..c1e592c --- /dev/null +++ b/librpc/include/rpcsvc/nfs_prot.x @@ -0,0 +1,1265 @@ +/* + * 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/librpc/include/rpcsvc/nis.x b/librpc/include/rpcsvc/nis.x new file mode 100644 index 0000000..ba6c6d1 --- /dev/null +++ b/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/librpc/include/rpcsvc/nis_cache.x b/librpc/include/rpcsvc/nis_cache.x new file mode 100644 index 0000000..8343cfd --- /dev/null +++ b/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/librpc/include/rpcsvc/nis_callback.x b/librpc/include/rpcsvc/nis_callback.x new file mode 100644 index 0000000..4e74aa0 --- /dev/null +++ b/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/librpc/include/rpcsvc/nis_db.h b/librpc/include/rpcsvc/nis_db.h new file mode 100644 index 0000000..71785b0 --- /dev/null +++ b/librpc/include/rpcsvc/nis_db.h @@ -0,0 +1,164 @@ +/* + * 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, + _DB_STATUS = 0xffffffff +}; +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, + _DB_ACTION = 0xffffffff +}; +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/librpc/include/rpcsvc/nis_object.x b/librpc/include/rpcsvc/nis_object.x new file mode 100644 index 0000000..3156724 --- /dev/null +++ b/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/librpc/include/rpcsvc/nis_tags.h b/librpc/include/rpcsvc/nis_tags.h new file mode 100644 index 0000000..0eaee6d --- /dev/null +++ b/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/librpc/include/rpcsvc/nislib.h b/librpc/include/rpcsvc/nislib.h new file mode 100644 index 0000000..9f874d2 --- /dev/null +++ b/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/librpc/include/rpcsvc/nlm_prot.x b/librpc/include/rpcsvc/nlm_prot.x new file mode 100644 index 0000000..fdc6d6e --- /dev/null +++ b/librpc/include/rpcsvc/nlm_prot.x @@ -0,0 +1,183 @@ +/* @(#)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/librpc/include/rpcsvc/pmap_prot.x b/librpc/include/rpcsvc/pmap_prot.x new file mode 100644 index 0000000..2e9c089 --- /dev/null +++ b/librpc/include/rpcsvc/pmap_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 +% */ +%/* +% * 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/librpc/include/rpcsvc/rex.x b/librpc/include/rpcsvc/rex.x new file mode 100644 index 0000000..928efa2 --- /dev/null +++ b/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/librpc/include/rpcsvc/rnusers.x b/librpc/include/rpcsvc/rnusers.x new file mode 100644 index 0000000..393eaf4 --- /dev/null +++ b/librpc/include/rpcsvc/rnusers.x @@ -0,0 +1,122 @@ +/* + * 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/librpc/include/rpcsvc/rquota.x b/librpc/include/rpcsvc/rquota.x new file mode 100644 index 0000000..72864d1 --- /dev/null +++ b/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/librpc/include/rpcsvc/rstat.x b/librpc/include/rpcsvc/rstat.x new file mode 100644 index 0000000..fee9d52 --- /dev/null +++ b/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/librpc/include/rpcsvc/spray.x b/librpc/include/rpcsvc/spray.x new file mode 100644 index 0000000..a4d086a --- /dev/null +++ b/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/librpc/include/rpcsvc/yp.x b/librpc/include/rpcsvc/yp.x new file mode 100644 index 0000000..aa87265 --- /dev/null +++ b/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/librpc/include/rpcsvc/yp_prot.h b/librpc/include/rpcsvc/yp_prot.h new file mode 100644 index 0000000..f29f3ce --- /dev/null +++ b/librpc/include/rpcsvc/yp_prot.h @@ -0,0 +1,330 @@ +/* + * 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, + _YPBIND_RESPTYPE = 0xffffffff +}; + +/* 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 (XDR *, datum *); +bool_t xdr_ypreq_key (XDR *, struct ypreq_key *); +bool_t xdr_ypreq_nokey (XDR *, struct ypreq_nokey *); +bool_t xdr_ypreq_xfr (XDR *, struct ypreq_xfr *); +bool_t xdr_ypresp_val (XDR *, struct ypresp_val *); +bool_t xdr_ypresp_key_val (XDR *, struct ypresp_key_val *); +bool_t xdr_ypbind_resp (XDR *, struct ypbind_resp *); +bool_t xdr_ypbind_setdom (XDR *, struct ypbind_setdom *); +bool_t xdr_yp_inaddr (XDR *, struct inaddr *); +bool_t xdr_ypmap_parms (XDR *, struct ypmap_parms *); +bool_t xdr_yppushresp_xfr (XDR *, struct yppushresp_xfr *); +bool_t xdr_ypresp_order (XDR *, struct ypresp_order *); +bool_t xdr_ypresp_master (XDR *, struct ypresp_master *); +bool_t xdr_ypresp_maplist (XDR *, struct ypresp_maplist *); +__END_DECLS + +#endif /* _RPCSVC_YP_PROT_H_ */ diff --git a/librpc/include/rpcsvc/ypclnt.h b/librpc/include/rpcsvc/ypclnt.h new file mode 100644 index 0000000..6b8edfe --- /dev/null +++ b/librpc/include/rpcsvc/ypclnt.h @@ -0,0 +1,93 @@ +/* + * 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) (unsigned long, char *, int, char *, int, void *); + char *data; /* opaque pointer for use of callback fn */ +}; + +struct dom_binding; + +__BEGIN_DECLS +int yp_bind (char *dom); +int _yp_dobind (char *dom, struct dom_binding **ypdb); +void yp_unbind (char *dom); +int yp_get_default_domain (char **domp); +int yp_match (char *indomain, char *inmap, + const char *inkey, int inkeylen, char **outval, + int *outvallen); +int yp_first (char *indomain, char *inmap, + char **outkey, int *outkeylen, char **outval, + int *outvallen); +int yp_next (char *indomain, char *inmap, + char *inkey, int inkeylen, char **outkey, + int *outkeylen, char **outval, int *outvallen); +int yp_master (char *indomain, char *inmap, char **outname); +int yp_order (char *indomain, char *inmap, int *outorder); +int yp_all (char *indomain, char *inmap, + struct ypall_callback *incallback); +char * yperr_string (int incode); +char * ypbinderr_string (int incode); +int ypprot_err (unsigned int incode); +__END_DECLS + +#endif /* _RPCSVC_YPCLNT_H_ */ diff --git a/librpc/include/rpcsvc/yppasswd.x b/librpc/include/rpcsvc/yppasswd.x new file mode 100644 index 0000000..73dca8e --- /dev/null +++ b/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 ( char * , struct x_passwd * ); +%#define yppasswd(x,y) _yppasswd(x,y) +#endif diff --git a/librpc/include/rpcsvc/ypupdate_prot.x b/librpc/include/rpcsvc/ypupdate_prot.x new file mode 100644 index 0000000..f16d5ee --- /dev/null +++ b/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/librpc/include/rpcsvc/ypxfrd.x b/librpc/include/rpcsvc/ypxfrd.x new file mode 100644 index 0000000..1845a4f --- /dev/null +++ b/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/librpc/src/rpc/DISCLAIMER b/librpc/src/rpc/DISCLAIMER new file mode 100644 index 0000000..1a66d5f --- /dev/null +++ b/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/librpc/src/rpc/README b/librpc/src/rpc/README new file mode 100644 index 0000000..ad9d70f --- /dev/null +++ b/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/librpc/src/rpc/auth_none.c b/librpc/src/rpc/auth_none.c new file mode 100644 index 0000000..535749c --- /dev/null +++ b/librpc/src/rpc/auth_none.c @@ -0,0 +1,140 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#define MAX_MARSHAL_SIZE 20 + +/* + * Authenticator operations routines + */ +static void authnone_verf(AUTH*); +static void authnone_destroy(AUTH*); +static int authnone_marshal(AUTH*, XDR*); +static int authnone_validate(AUTH*, struct opaque_auth *); +static int authnone_refresh(AUTH*); + +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_MARSHAL_SIZE]; + u_int mcnt; +} *authnone_private; + +AUTH * +authnone_create(void) +{ + struct authnone_private *ap = authnone_private; + XDR xdr_stream; + 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_MARSHAL_SIZE, + XDR_ENCODE); + (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); + (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS(xdrs); + XDR_DESTROY(xdrs); + } + return (&ap->no_client); +} + +/*ARGSUSED*/ +static int +authnone_marshal(AUTH *client, XDR *xdrs) +{ + 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(AUTH *client) +{ +} + +static int +authnone_validate(AUTH *client, struct opaque_auth *opaque) +{ + + return (TRUE); +} + +static int +authnone_refresh(AUTH *client) +{ + + return (FALSE); +} + +static void +authnone_destroy(AUTH *client) +{ +} diff --git a/librpc/src/rpc/auth_unix.c b/librpc/src/rpc/auth_unix.c new file mode 100644 index 0000000..99f5920 --- /dev/null +++ b/librpc/src/rpc/auth_unix.c @@ -0,0 +1,347 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Unix authenticator operations vector + */ +static void authunix_nextverf(AUTH*); +static int authunix_marshal(AUTH*, XDR*); +static int authunix_validate(AUTH*, struct opaque_auth *); +static int authunix_refresh(AUTH*); +static void authunix_destroy(AUTH*); + +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(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( + char *machname, + int uid, + int gid, + 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(void) +{ + 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) +{ + /* no action necessary */ +} + +static int +authunix_marshal(AUTH *auth, XDR *xdrs) +{ + struct audata *au = AUTH_PRIVATE(auth); + + return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); +} + +static int +authunix_validate( 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 int +authunix_refresh(AUTH *auth) +{ + struct audata *au = AUTH_PRIVATE(auth); + struct authunix_parms aup; + struct timeval now; + XDR xdrs; + 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 *auth) +{ + 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 *auth) +{ + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + 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/librpc/src/rpc/authunix_prot.c b/librpc/src/rpc/authunix_prot.c new file mode 100644 index 0000000..9dc867a --- /dev/null +++ b/librpc/src/rpc/authunix_prot.c @@ -0,0 +1,73 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +/* + * XDR for unix authentication parameters. + */ +bool_t +xdr_authunix_parms( + XDR *xdrs, + 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 *)(void *)&(p->aup_gids), + &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t) xdr_int) ) { + return (TRUE); + } + return (FALSE); +} diff --git a/librpc/src/rpc/bindresvport.3 b/librpc/src/rpc/bindresvport.3 new file mode 100644 index 0000000..02a079d --- /dev/null +++ b/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/librpc/src/rpc/bindresvport.c b/librpc/src/rpc/bindresvport.c new file mode 100644 index 0000000..1c979de --- /dev/null +++ b/librpc/src/rpc/bindresvport.c @@ -0,0 +1,162 @@ +#include "rtems-rpc-config.h" + +/* $NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include +#include +#include + +#include + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport( + int sd, + struct sockaddr_in *sin) +{ + return bindresvport_sa(sd, (struct sockaddr *)sin); +} + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport_sa( + int sd, + struct sockaddr *sa) +{ + int old, error, af; + struct sockaddr myaddr; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif + int proto, portrange, portlow; + u_int16_t port; + socklen_t 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; + + switch (af) { + case AF_INET: + proto = IPPROTO_IP; + portrange = IP_PORTRANGE; + portlow = IP_PORTRANGE_LOW; + sin = (struct sockaddr_in *)sa; + salen = sizeof(struct sockaddr_in); + port = sin->sin_port; + break; +#ifdef INET6 + case AF_INET6: + proto = IPPROTO_IPV6; + portrange = IPV6_PORTRANGE; + portlow = IPV6_PORTRANGE_LOW; + sin6 = (struct sockaddr_in6 *)sa; + salen = sizeof(struct sockaddr_in6); + port = sin6->sin6_port; + break; +#endif + default: + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + sa->sa_len = salen; + + if (port == 0) { + socklen_t oldlen = sizeof(old); + + error = getsockopt(sd, proto, portrange, &old, &oldlen); + if (error < 0) + return (error); + + error = setsockopt(sd, proto, portrange, &portlow, + sizeof(portlow)); + if (error < 0) + return (error); + } + + 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); +} diff --git a/librpc/src/rpc/clnt_generic.c b/librpc/src/rpc/clnt_generic.c new file mode 100644 index 0000000..6d97dfb --- /dev/null +++ b/librpc/src/rpc/clnt_generic.c @@ -0,0 +1,147 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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( + const char *hostname, + rpcprog_t prog, + rpcvers_t vers, + const 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/librpc/src/rpc/clnt_perror.c b/librpc/src/rpc/clnt_perror.c new file mode 100644 index 0000000..121ebc9 --- /dev/null +++ b/librpc/src/rpc/clnt_perror.c @@ -0,0 +1,261 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +static char *auth_errmsg(enum auth_stat stat); +#define CLNT_PERROR_BUFLEN 256 + +#define buf (rtems_rpc_task_variables->clnt_perror_buf) + +static char * +_buf(void) +{ + + if (buf == 0) + buf = (char *)malloc(CLNT_PERROR_BUFLEN); + return (buf); +} + +/* + * Print reply error info + */ +char * +clnt_sperror( + CLIENT *rpch, + const 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( + CLIENT *rpch, + const 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( + 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( + enum clnt_stat num) +{ + (void) fprintf(stderr,"%s\n",clnt_sperrno(num)); +} + + +char * +clnt_spcreateerror( + const 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( + const 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( + 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/librpc/src/rpc/clnt_raw.c b/librpc/src/rpc/clnt_raw.c new file mode 100644 index 0000000..8682622 --- /dev/null +++ b/librpc/src/rpc/clnt_raw.c @@ -0,0 +1,250 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 kernel. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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]; + union { + struct rpc_msg mashl_rpcmsg; + char mashl_callmsg[MCALL_MSG_SIZE]; + } u; + u_int mcnt; +}; +#define clntraw_private (rtems_rpc_task_variables->clnt_raw_private) + +static enum clnt_stat clntraw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, void *argsp, xdrproc_t xresults, void *resultsp, struct timeval timeout); +static void clntraw_abort(void); +static void clntraw_geterr(CLIENT *h, struct rpc_err*); +static bool_t clntraw_freeres(CLIENT *, xdrproc_t, void*); +static bool_t clntraw_control(CLIENT *, int, char *); +static void clntraw_destroy(CLIENT *); + +static struct clnt_ops client_ops = { + clntraw_call, + clntraw_abort, + clntraw_geterr, + clntraw_freeres, + clntraw_destroy, + clntraw_control +}; + +/* + * Create a client handle for memory based rpc. + */ +CLIENT * +clntraw_create( + u_long prog, + u_long vers ) +{ + 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->u.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( + CLIENT *h, + rpcproc_t proc, + xdrproc_t xargs, + void *argsp, + xdrproc_t xresults, + void *resultsp, + struct timeval timeout ) +{ + struct clnt_raw_private *clp = clntraw_private; + 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); + clp->u.mashl_rpcmsg.rm_xid ++ ; + if ((! XDR_PUTBYTES(xdrs, clp->u.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(CLIENT *cl, struct rpc_err *err) +{ +} + + +static bool_t +clntraw_freeres( + CLIENT *cl, + xdrproc_t xdr_res, + void *res_ptr ) +{ + struct clnt_raw_private *clp = clntraw_private; + 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(void) +{ +} + +static bool_t +clntraw_control(CLIENT *cl, int request, char *info) +{ + return (FALSE); +} + +static void +clntraw_destroy(CLIENT *cl) +{ +} diff --git a/librpc/src/rpc/clnt_simple.c b/librpc/src/rpc/clnt_simple.c new file mode 100644 index 0000000..6767a78 --- /dev/null +++ b/librpc/src/rpc/clnt_simple.c @@ -0,0 +1,129 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 (rtems_rpc_task_variables->call_rpc_private) + +int +callrpc( + char *host, + int prognum, int versnum, int procnum, + xdrproc_t inproc, char *in, + xdrproc_t outproc, char *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)_RPC_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/librpc/src/rpc/clnt_tcp.c b/librpc/src/rpc/clnt_tcp.c new file mode 100644 index 0000000..b7ccd5a --- /dev/null +++ b/librpc/src/rpc/clnt_tcp.c @@ -0,0 +1,608 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCALL_MSG_SIZE 24 + +static int readtcp(char *, char*, int); +static int writetcp(char *, char*, int); + +static enum clnt_stat clnttcp_call(CLIENT *, rpcproc_t, xdrproc_t, void*, xdrproc_t, void*, struct timeval); +static void clnttcp_abort(void); +static void clnttcp_geterr(CLIENT *, struct rpc_err*); +static bool_t clnttcp_freeres(CLIENT *, xdrproc_t, void*); +static bool_t clnttcp_control(CLIENT *, int, char *); +static void clnttcp_destroy(CLIENT *); + +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; /* close it on destroy */ + struct timeval ct_wait; /* wait interval in milliseconds */ + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_in ct_addr; + struct rpc_err ct_error; + union { + char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int32_t ct_mcalli; + } ct_u; + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; /* XDR stream */ +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +CLIENT * +clnttcp_create( + struct sockaddr_in *raddr, + u_long prog, /* program number */ + u_long vers, /* version number */ + int *sockp, + u_int sendsz, + u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct = NULL; /* client handle */ + struct timeval now; + struct rpc_msg call_msg; + static uintptr_t disrupt; + + if (disrupt == 0) + disrupt = (uintptr_t)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)_RPC_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_u.ct_mcallc, MCALL_MSG_SIZE, + XDR_ENCODE); + if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { + if (ct->ct_closeit) { + (void)_RPC_close(*sockp); + } + goto fooy; + } + ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); + XDR_DESTROY(&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t)ct, readtcp, writetcp); + h->cl_ops = &tcp_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create(); + return (h); + +fooy: + /* + * Something goofed, free stuff and barf + */ + if (ct) + mem_free((caddr_t)ct, sizeof(struct ct_data)); + if (h) + mem_free((caddr_t)h, sizeof(CLIENT)); + return ((CLIENT *)NULL); +} + +static enum clnt_stat +clnttcp_call( + CLIENT *h, + rpcproc_t proc, + xdrproc_t xdr_args, + void *args_ptr, + xdrproc_t xdr_results, + void *results_ptr, + struct timeval timeout) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_int32_t x_id; + u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */ + bool_t shipnow; + int refreshes = 2; + + 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_u.ct_mcallc, 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 = (xdrproc_t)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( + CLIENT *h, + struct rpc_err *errp) +{ + struct ct_data *ct; + + ct = (struct ct_data *) h->cl_private; + *errp = ct->ct_error; +} + +static bool_t +clnttcp_freeres( + CLIENT *cl, + xdrproc_t xdr_res, + void *res_ptr) +{ + struct ct_data *ct; + XDR *xdrs; + + ct = (struct ct_data *)cl->cl_private; + xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clnttcp_abort(void) +{ +} + + +static bool_t +clnttcp_control( + CLIENT *cl, + int request, + char *info) +{ + struct ct_data *ct; + struct timeval *tv; + socklen_t len; + + ct = (struct ct_data *)cl->cl_private; + + 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_int32_t *)info = + ntohl(*(u_int32_t *)&ct->ct_u.ct_mcalli); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + if (info == NULL) + return(FALSE); + *(u_int32_t *)&ct->ct_u.ct_mcalli = + htonl(*((u_int32_t *)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_int32_t *)info = + ntohl(*(u_int32_t *)(ct->ct_u.ct_mcallc + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + if (info == NULL) + return(FALSE); + *(u_int32_t *)(ct->ct_u.ct_mcallc + + 4 * BYTES_PER_XDR_UNIT) = + htonl(*(u_int32_t *)info); + break; + + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the fourth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + if (info == NULL) + return(FALSE); + *(u_int32_t *)info = ntohl(*(u_int32_t *)(ct->ct_u.ct_mcallc + + 3 * BYTES_PER_XDR_UNIT)); + break; + + case CLSET_PROG: + if (info == NULL) + return(FALSE); + *(u_int32_t *)(ct->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_int32_t *)info); + break; + + case CLGET_LOCAL_ADDR: + len = sizeof(struct sockaddr); + if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0) + return(FALSE); + break; + + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return (FALSE); + } + return (TRUE); +} + + +static void +clnttcp_destroy( + CLIENT *h) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) { + (void)_RPC_close(ct->ct_sock); + } + XDR_DESTROY(&(ct->ct_xdrs)); + mem_free(ct, sizeof(struct ct_data)); + mem_free(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( + char *_ct, + char *buf, + int len) +{ + struct ct_data *ct = (struct ct_data*) _ct; + 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 = _RPC_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( + char *_ct, + char *buf, + int len) +{ + struct ct_data *ct = (struct ct_data *) _ct; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = _RPC_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/librpc/src/rpc/clnt_udp.c b/librpc/src/rpc/clnt_udp.c new file mode 100644 index 0000000..93befc2 --- /dev/null +++ b/librpc/src/rpc/clnt_udp.c @@ -0,0 +1,582 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * UDP bases client side rpc operations + */ +static enum clnt_stat clntudp_call(CLIENT *, rpcproc_t, xdrproc_t, void*, xdrproc_t, void*, struct timeval); +static void clntudp_abort(void); +static void clntudp_geterr(CLIENT *, struct rpc_err*); +static bool_t clntudp_freeres(CLIENT *, xdrproc_t, void*); +static bool_t clntudp_control(CLIENT *, int, char *); +static void clntudp_destroy(CLIENT *); + +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; /* opened by library */ + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; /* retransmit interval */ + struct timeval cu_total; /* total time for the call */ + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; /* send size */ + union { + u_int32_t *pi32; + char *c; + } _cu_outbuf; +#define cu_outbuf _cu_outbuf.c + u_int cu_recvsz; /* recv size */ + union { + u_int32_t i32; + char c[1]; + } _cu_inbuf; +#define cu_inbuf _cu_inbuf.c +}; + +/* + * Create a UDP based client handle. + * If *sockp<0, *sockp is set to a newly created UPD socket. + * If raddr->sin_port is 0 a binder on the remote machine + * is consulted for the correct port number. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is initialized to null authentication. + * Caller may wish to set this something more useful. + * + * wait is the amount of time used between retransmitting a call if + * no response has been heard; retransmition occurs until the actual + * rpc call times out. + * + * sendsz and recvsz are the maximum allowable packet sizes that can be + * sent and received. + */ +CLIENT * +clntudp_bufcreate( + struct sockaddr_in *raddr, + u_long program, /* program number */ + u_long version, /* version number */ + struct timeval wait, + int *sockp, + u_int sendsz, + u_int recvsz) +{ + CLIENT *cl = NULL; /* client handle */ + struct cu_data *cu = NULL; /* private data */ + struct timeval now; + struct rpc_msg call_msg; + static uintptr_t disrupt; + + if (disrupt == 0) + disrupt = (uintptr_t)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 = 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( + struct sockaddr_in *raddr, + u_long program, /* program number */ + u_long version, /* version number */ + struct timeval wait, + int *sockp) +{ + + return(clntudp_bufcreate(raddr, program, version, wait, sockp, + UDPMSGSIZE, UDPMSGSIZE)); +} + +static enum clnt_stat +clntudp_call( + CLIENT *cl, /* client handle */ + rpcproc_t proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + void *argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + void *resultsp, /* pointer to results */ + struct timeval utimeout ) /* seconds to wait before giving up */ +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + XDR *xdrs; + size_t outlen = 0; + int inlen; + socklen_t 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 = (size_t)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 ( cu->_cu_inbuf.i32 != *cu->_cu_outbuf.pi32 ) + 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( + CLIENT *cl, + struct rpc_err *errp) +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + + *errp = cu->cu_error; +} + + +static bool_t +clntudp_freeres( + CLIENT *cl, + xdrproc_t xdr_res, + void *res_ptr) +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + XDR *xdrs = &(cu->cu_outxdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clntudp_abort(void) +{ +} + + +static bool_t +clntudp_control( + CLIENT *cl, + int request, + char *info) +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + struct timeval *tv; + socklen_t 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 fourth 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( + CLIENT *cl) +{ + struct cu_data *cu = (struct cu_data *)cl->cl_private; + + if (cu->cu_closeit) { + (void)_RPC_close(cu->cu_sock); + } + XDR_DESTROY(&(cu->cu_outxdrs)); + mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz)); + mem_free(cl, sizeof (CLIENT)); +} diff --git a/librpc/src/rpc/des_crypt.3 b/librpc/src/rpc/des_crypt.3 new file mode 100644 index 0000000..a92f577 --- /dev/null +++ b/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/librpc/src/rpc/get_myaddress.c b/librpc/src/rpc/get_myaddress.c new file mode 100644 index 0000000..a3410e9 --- /dev/null +++ b/librpc/src/rpc/get_myaddress.c @@ -0,0 +1,143 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Determine the size of an ifreq structure when addresses larger + * than the pifreq structure size may be returned from the kernel. + */ +static size_t ifreqSize ( struct ifreq *pifreq ) +{ + size_t size = pifreq->ifr_addr.sa_len + sizeof(pifreq->ifr_name); + if ( size < sizeof ( *pifreq ) ) { + size = sizeof ( *pifreq ); + } + return size; +} + +/* + * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces. We return information from a loopback + * interface only if there are no other possible interfaces. + */ +int +get_myaddress( + struct sockaddr_in *addr) +{ + int s; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + int loopback = 0, gotit = 0; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return(-1); + } +again: + ifc.ifc_len = sizeof ( struct ifreq ) * 8u; + ifc.ifc_buf = malloc ( ifc.ifc_len ); + if ( ! ifc.ifc_buf ) { + _RPC_close(s); + return -1; + } + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { + _RPC_close(s); + free ( ifc.ifc_buf ); + return(-1); + } + ifr = ifc.ifc_req; + + while ( ifc.ifc_len >= ifreqSize ( ifr ) ) { + ifreq = *ifr; + if (ioctl(s, SIOCGIFFLAGS, (char *) &ifreq ) < 0) { + _RPC_close(s); + free ( ifc.ifc_buf ); + 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; + } + + const size_t len = ifreqSize ( ifr ); + ifc.ifc_len -= len; + /* + * RTEMS seems to require copy up to properly aligned + * boundary at the beginning of the buffer? + */ + memmove ( ifr, len + (char *) ifr, ifc.ifc_len ); + } + if (gotit == 0 && loopback == 0) { + free ( ifc.ifc_buf ); + loopback = 1; + goto again; + } + (void)_RPC_close(s); + free ( ifc.ifc_buf ); + return (gotit ? 0 : -1); +} diff --git a/librpc/src/rpc/getrpcent.3 b/librpc/src/rpc/getrpcent.3 new file mode 100644 index 0000000..1e92e9d --- /dev/null +++ b/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/librpc/src/rpc/getrpcent.c b/librpc/src/rpc/getrpcent.c new file mode 100644 index 0000000..a980c7d --- /dev/null +++ b/librpc/src/rpc/getrpcent.c @@ -0,0 +1,303 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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(char *val, int len); + +static char RPCDB[] = "/etc/rpc"; + +static struct rpcdata * +_rpcdata(void) +{ + register struct rpcdata *d = rpcdata; + + if (d == 0) { + d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata)); + rpcdata = d; + } + return (d); +} + +struct rpcent * +getrpcbynumber(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(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(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(void) +{ + 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(void) +{ + 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( + 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/librpc/src/rpc/getrpcport.3 b/librpc/src/rpc/getrpcport.3 new file mode 100644 index 0000000..0e9175e --- /dev/null +++ b/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/librpc/src/rpc/getrpcport.c b/librpc/src/rpc/getrpcport.c new file mode 100644 index 0000000..f1fa5a3 --- /dev/null +++ b/librpc/src/rpc/getrpcport.c @@ -0,0 +1,71 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +int +getrpcport( + char *host, + int prognum, + int versnum, + int 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/librpc/src/rpc/netname.c b/librpc/src/rpc/netname.c new file mode 100644 index 0000000..fd1145c --- /dev/null +++ b/librpc/src/rpc/netname.c @@ -0,0 +1,141 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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(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( + 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( + 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/librpc/src/rpc/netnamer.c b/librpc/src/rpc/netnamer.c new file mode 100644 index 0000000..841f6b1 --- /dev/null +++ b/librpc/src/rpc/netnamer.c @@ -0,0 +1,333 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 ( char *, char * ); +static int _getgroups ( char *, gid_t * ); + +#ifndef NGROUPS +#define NGROUPS 16 +#endif + +/* + * Convert network-name into unix credential + */ +int +netname2user( + 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( + 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( + 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( + char *key, + char *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/librpc/src/rpc/pmap_clnt.c b/librpc/src/rpc/pmap_clnt.c new file mode 100644 index 0000000..7aab450 --- /dev/null +++ b/librpc/src/rpc/pmap_clnt.c @@ -0,0 +1,153 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +static struct timeval timeout = { 5, 0 }; +static struct timeval tottimeout = { 60, 0 }; + +#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( + u_long program, + u_long version, + int protocol, + int port) /* was u_short but changed to match prototype */ +{ + struct sockaddr_in myaddress; + int socket = -1; + 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, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_bool, &rslt, + tottimeout) != RPC_SUCCESS) { + clnt_perror(client, "Cannot register service"); + return (FALSE); + } + CLNT_DESTROY(client); + if (socket != -1) + (void)_RPC_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( + 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, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_bool, &rslt, + tottimeout); + CLNT_DESTROY(client); + if (socket != -1) + (void)_RPC_close(socket); + return (rslt); +} diff --git a/librpc/src/rpc/pmap_getmaps.c b/librpc/src/rpc/pmap_getmaps.c new file mode 100644 index 0000000..1645c5d --- /dev/null +++ b/librpc/src/rpc/pmap_getmaps.c @@ -0,0 +1,93 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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(struct sockaddr_in *address) +{ + struct pmaplist *head = NULL; + int socket = -1; + struct timeval minutetimeout; + 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 != NULL) { + if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP, + (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_pmaplist, &head, minutetimeout) != + RPC_SUCCESS) { + clnt_perror(client, "pmap_getmaps rpc problem"); + } + CLNT_DESTROY(client); + } + if (socket != -1) + (void)_RPC_close(socket); + address->sin_port = 0; + return (head); +} diff --git a/librpc/src/rpc/pmap_getport.c b/librpc/src/rpc/pmap_getport.c new file mode 100644 index 0000000..9a28937 --- /dev/null +++ b/librpc/src/rpc/pmap_getport.c @@ -0,0 +1,99 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +static const struct timeval timeout = { 5, 0 }; +static const 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( + struct sockaddr_in *address, + u_long program, + u_long version, + u_int protocol ) +{ + u_short port = 0; + int socket = -1; + CLIENT *client; + struct pmap parms; + + address->sin_port = htons(PMAPPORT); + client = clntudp_bufcreate(address, PMAPPROG, + PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != NULL) { + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = 0; /* not needed or used */ + if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, + (xdrproc_t)xdr_pmap, + &parms, (xdrproc_t)xdr_u_short, &port, tottimeout) != + RPC_SUCCESS){ + rpc_createerr.cf_stat = RPC_PMAPFAILURE; + clnt_geterr(client, &rpc_createerr.cf_error); + } else if (port == 0) { + rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; + } + CLNT_DESTROY(client); + } + if (socket != -1) + (void)_RPC_close(socket); + address->sin_port = 0; + return (port); +} diff --git a/librpc/src/rpc/pmap_prot.c b/librpc/src/rpc/pmap_prot.c new file mode 100644 index 0000000..33b0d0d --- /dev/null +++ b/librpc/src/rpc/pmap_prot.c @@ -0,0 +1,65 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +bool_t +xdr_pmap( + 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/librpc/src/rpc/pmap_prot2.c b/librpc/src/rpc/pmap_prot2.c new file mode 100644 index 0000000..c61eab5 --- /dev/null +++ b/librpc/src/rpc/pmap_prot2.c @@ -0,0 +1,124 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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( + XDR *xdrs, + struct pmaplist **rp) +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + 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), (xdrproc_t) xdr_pmap)) + return (FALSE); + rp = (freeing) ? next : &((*rp)->pml_next); + } +} diff --git a/librpc/src/rpc/pmap_rmt.c b/librpc/src/rpc/pmap_rmt.c new file mode 100644 index 0000000..5576c87 --- /dev/null +++ b/librpc/src/rpc/pmap_rmt.c @@ -0,0 +1,444 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MAX_BROADCAST_SIZE 1400 + +static const struct timeval timeout = { 3, 0 }; + +/* + * pmapper remote-call-service interface. + * This routine is used to call the pmapper remote call service + * which will look up a service program in the port maps, and then + * remotely call that routine with the given parameters. This allows + * programs to do a lookup and call in one step. +*/ +enum clnt_stat +pmap_rmtcall( + struct sockaddr_in *addr, + u_long prog, + u_long vers, + u_long proc, + xdrproc_t xdrargs, + caddr_t argsp, + xdrproc_t xdrres, + caddr_t resp, + struct timeval tout, + u_long *port_ptr) +{ + int sock = -1; + CLIENT *client; + struct rmtcallargs a; + struct rmtcallres r; + enum clnt_stat stat; + + assert(addr != NULL); + assert(port_ptr != NULL); + + addr->sin_port = htons(PMAPPORT); + client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock); + if (client != NULL) { + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.args_ptr = argsp; + a.xdr_args = xdrargs; + r.port_ptr = port_ptr; + r.results_ptr = resp; + r.xdr_results = xdrres; + stat = CLNT_CALL(client, (rpcproc_t)PMAPPROC_CALLIT, + (xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres, + &r, tout); + CLNT_DESTROY(client); + } else { + stat = RPC_FAILED; + } + if (sock != -1) + (void)_RPC_close(sock); + addr->sin_port = 0; + return (stat); +} + + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rmtcall_args( + XDR *xdrs, + struct rmtcallargs *cap) +{ + u_int lenposition, argposition, position; + + assert(xdrs != NULL); + assert(cap != NULL); + + if (xdr_u_long(xdrs, &(cap->prog)) && + xdr_u_long(xdrs, &(cap->vers)) && + xdr_u_long(xdrs, &(cap->proc))) { + 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( + XDR *xdrs, + struct rmtcallres *crp) +{ + caddr_t port_ptr; + + assert(xdrs != NULL); + assert(crp != NULL); + + port_ptr = (caddr_t)(void *)crp->port_ptr; + if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), + (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { + crp->port_ptr = (u_long *)(void *)port_ptr; + return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); + } + return (FALSE); +} + + +/* + * The following is kludged-up support for simple rpc broadcasts. + * Someday a large, complicated system will replace these trivial + * routines which only support udp/ip . + */ + +static int +getbroadcastnets( + struct in_addr *addrs, + int sock, /* any valid socket will do */ + char *buf /* why allocxate more when we can use existing... */ ) +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct sockaddr_in *sin; + struct in_addr addr; + char *cp, *cplim; + int n, i = 0; + + ifc.ifc_len = UDPMSGSIZE; + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + perror("broadcast: ioctl (get interface configuration)"); + return (0); + } +#define max(a, b) (a > b ? a : b) +#define size(p) max((p).sa_len, sizeof(p)) + cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; + cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { + ifr = (struct ifreq *)cp; + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + 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)(caddr_t, struct sockaddr_in *); + +enum clnt_stat +clnt_broadcast( + u_long prog, /* program number */ + u_long vers, /* version number */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + caddr_t argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + caddr_t resultsp, /* pointer to results */ + resultproc_t eachresult /* call with each result obtained */ ) +{ + enum clnt_stat stat = RPC_SUCCESS; /* to avoid warning */ + AUTH *unix_auth = authunix_create_default(); + XDR xdr_stream; + register XDR *xdrs = &xdr_stream; + int outlen, inlen, nets; + socklen_t fromlen; + 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 uintptr_t disrupt; + + if (disrupt == 0) + disrupt = (uintptr_t) 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 = (xdrproc_t) 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 = (xdrproc_t) xdr_void; + (void)xdr_replymsg(xdrs, &msg); + (void)(*xresults)(xdrs, resultsp); + xdr_destroy(xdrs); + if (done) { + stat = RPC_SUCCESS; + goto done_broad; + } else { + goto recv_again; + } + } +done_broad: + if (fds != &readfds) + free(fds); + if (sock >= 0) + (void)_RPC_close(sock); + AUTH_DESTROY(unix_auth); + return (stat); +} diff --git a/librpc/src/rpc/publickey.3 b/librpc/src/rpc/publickey.3 new file mode 100644 index 0000000..29094f9 --- /dev/null +++ b/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/librpc/src/rpc/publickey.5 b/librpc/src/rpc/publickey.5 new file mode 100644 index 0000000..9f7a325 --- /dev/null +++ b/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/librpc/src/rpc/rpc.3 b/librpc/src/rpc/rpc.3 new file mode 100644 index 0000000..f40b643 --- /dev/null +++ b/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/librpc/src/rpc/rpc.5 b/librpc/src/rpc/rpc.5 new file mode 100644 index 0000000..36f895d --- /dev/null +++ b/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/librpc/src/rpc/rpc_callmsg.c b/librpc/src/rpc/rpc_callmsg.c new file mode 100644 index 0000000..2d340ba --- /dev/null +++ b/librpc/src/rpc/rpc_callmsg.c @@ -0,0 +1,198 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +/* + * XDR a call message + */ +bool_t +xdr_callmsg( + XDR *xdrs, + 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 *)(void *)&(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/librpc/src/rpc/rpc_commondata.c b/librpc/src/rpc/rpc_commondata.c new file mode 100644 index 0000000..cae9d21 --- /dev/null +++ b/librpc/src/rpc/rpc_commondata.c @@ -0,0 +1,47 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#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/librpc/src/rpc/rpc_dtablesize.c b/librpc/src/rpc/rpc_dtablesize.c new file mode 100644 index 0000000..d19cc04 --- /dev/null +++ b/librpc/src/rpc/rpc_dtablesize.c @@ -0,0 +1,67 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#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/librpc/src/rpc/rpc_prot.c b/librpc/src/rpc/rpc_prot.c new file mode 100644 index 0000000..ea4787e --- /dev/null +++ b/librpc/src/rpc/rpc_prot.c @@ -0,0 +1,338 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +static void accepted(enum accept_stat, struct rpc_err *); +static void rejected(enum reject_stat, struct rpc_err *); + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +extern struct opaque_auth _null_auth; + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth( + XDR *xdrs, + struct opaque_auth *ap) +{ + + assert(xdrs != NULL); + assert(ap != NULL); + + if (xdr_enum(xdrs, &(ap->oa_flavor))) + return (xdr_bytes(xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES)); + return (FALSE); +} + +/* + * XDR a DES block + */ +bool_t +xdr_des_block( + XDR *xdrs, + des_block *blkp) +{ + + assert(xdrs != NULL); + assert(blkp != NULL); + + 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( + XDR *xdrs, + 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 *)(void *)&(ar->ar_stat))) + return (FALSE); + switch (ar->ar_stat) { + + case SUCCESS: + return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); + + case PROG_MISMATCH: + if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) + return (FALSE); + return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); + + case GARBAGE_ARGS: + case SYSTEM_ERR: + case PROC_UNAVAIL: + case PROG_UNAVAIL: + break; + } + return (TRUE); /* TRUE => open ended set of problems */ +} + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply( + XDR *xdrs, + struct rejected_reply *rr ) +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_enum(xdrs, (enum_t *)(void *)&(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 *)(void *)&(rr->rj_why))); + } + return (FALSE); +} + +static const struct xdr_discrim reply_dscrm[3] = { + { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, + { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, + { __dontcare__, NULL_xdrproc_t } }; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg( + XDR *xdrs, + struct rpc_msg *rmsg) +{ + if ( + xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)(void *)&(rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY) ) + return (xdr_union(xdrs, (enum_t *)(void *)&(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( + XDR *xdrs, + 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 *)(void *)&(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( + enum accept_stat acpt_stat, + struct rpc_err *error) +{ + + assert(error != NULL); + + switch (acpt_stat) { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (int32_t)MSG_ACCEPTED; + error->re_lb.s2 = (int32_t)acpt_stat; +} + +static void +rejected( + enum reject_stat rjct_stat, + struct rpc_err *error) +{ + + assert(error != NULL); + + switch (rjct_stat) { + case RPC_MISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (int32_t)MSG_DENIED; + error->re_lb.s2 = (int32_t)rjct_stat; +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply( + struct rpc_msg *msg, + struct rpc_err *error) +{ + + assert(msg != NULL); + assert(error != NULL); + + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) { + + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) { + error->re_status = RPC_SUCCESS; + return; + } + accepted(msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected(msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + + case RPC_FAILED: + case RPC_SUCCESS: + case RPC_PROGNOTREGISTERED: + case RPC_PMAPFAILURE: + case RPC_UNKNOWNPROTO: + case RPC_UNKNOWNHOST: + case RPC_SYSTEMERROR: + case RPC_CANTDECODEARGS: + case RPC_PROCUNAVAIL: + case RPC_PROGUNAVAIL: + case RPC_TIMEDOUT: + case RPC_CANTRECV: + case RPC_CANTSEND: + case RPC_CANTDECODERES: + case RPC_CANTENCODEARGS: + default: + break; + } +} diff --git a/librpc/src/rpc/rpc_secure.3 b/librpc/src/rpc/rpc_secure.3 new file mode 100644 index 0000000..4efd9b8 --- /dev/null +++ b/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/librpc/src/rpc/rpcdname.c b/librpc/src/rpc/rpcdname.c new file mode 100644 index 0000000..2451d63 --- /dev/null +++ b/librpc/src/rpc/rpcdname.c @@ -0,0 +1,86 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +int getdomainname(char *, size_t); + +#define default_domain (rtems_rpc_task_variables->rpcdname_default_domain) + +static char * +get_default_domain(void) +{ + char temp[256]; + + if (default_domain) + return (default_domain); + if (getdomainname(temp, sizeof(temp)) < 0) + return (0); + if (strlen(temp) > 0) { + default_domain = (char *)malloc((strlen(temp)+(size_t)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( + char **domain ) +{ + if ((*domain = get_default_domain()) != 0) + return (0); + return (-1); +} diff --git a/librpc/src/rpc/rstat.1 b/librpc/src/rpc/rstat.1 new file mode 100644 index 0000000..6cc47c2 --- /dev/null +++ b/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/librpc/src/rpc/rstat_svc.8 b/librpc/src/rpc/rstat_svc.8 new file mode 100644 index 0000000..e2eae8b --- /dev/null +++ b/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/librpc/src/rpc/rtems-rpc-config.h b/librpc/src/rpc/rtems-rpc-config.h new file mode 100644 index 0000000..9448ab7 --- /dev/null +++ b/librpc/src/rpc/rtems-rpc-config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RTEMS_RPC_CONFIG_H_ +#define _RTEMS_RPC_CONFIG_H_ + +#define _RPC_read read +#define _RPC_write write +#define _RPC_close close +#define _RTEMS_RPC_INTERNAL_ + +#endif /* _RTEMS_RPC_CONFIG_H_ */ diff --git a/librpc/src/rpc/rtems_portmapper.c b/librpc/src/rpc/rtems_portmapper.c new file mode 100644 index 0000000..8118482 --- /dev/null +++ b/librpc/src/rpc/rtems_portmapper.c @@ -0,0 +1,502 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt); +static void callit(struct svc_req *rqstp, SVCXPRT *xprt); +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_exit(); + } + + 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_exit(); + } + + if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { + fprintf(stderr, "couldn't do udp_create\n"); + close (sock); + rtems_task_exit(); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc(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_exit(); + } + if (bind(sock, (struct sockaddr *)&addr, len) != 0) { + perror("portmap cannot bind"); + close (sock); + rtems_task_exit(); + } + if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) + == (SVCXPRT *)NULL) { + fprintf(stderr, "couldn't do tcp_create\n"); + close (sock); + rtems_task_exit(); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc(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_exit(); +} + +static struct pmaplist * +find_service( + u_long prog, + u_long vers, + int prot ) +{ + register struct pmaplist *hit = NULL; + register struct pmaplist *pml; + + for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { + if ((pml->pml_map.pm_prog != prog) || + (pml->pml_map.pm_prot != prot)) + continue; + hit = pml; + if (pml->pml_map.pm_vers == vers) + break; + } + return (hit); +} + +/* + * 1 OK, 0 not + */ +static void reg_service( + 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, (xdrproc_t) xdr_void, NULL)) && + debugging) { + abort(); + } + break; + + case PMAPPROC_SET: + /* + * Set a program,version to port mapping + */ + if (!svc_getargs(xprt, (xdrproc_t) 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(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, (xdrproc_t) 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, (xdrproc_t) 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, (xdrproc_t) 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, (xdrproc_t) 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, (xdrproc_t) 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, (xdrproc_t) xdr_void, NULL)) + svcerr_decode(xprt); + else { + if ((!svc_sendreply(xprt, (xdrproc_t) 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( + XDR *xdrs, + struct encap_parms *epp ) +{ + + u_int temp_epp_arglen = epp->arglen; + return (xdr_bytes(xdrs, &(epp->args), &temp_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( + 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( + 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( + XDR *xdrs, + void *args, + ... ) +{ + struct rmtcallargs *cap = (struct rmtcallargs *) args; + + return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); +} + +/* + * This routine finds and sets the length of incoming opaque paraters + * and then calls xdr_opaque_parms. + */ +static bool_t +xdr_len_opaque_parms( + XDR *xdrs, + void *args, + ... ) +{ + struct rmtcallargs *cap = (struct rmtcallargs *) args; + 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( + 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, (xdrproc_t) 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, (xdrproc_t) 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, + ARGSIZE + 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/librpc/src/rpc/rtems_rpc.c b/librpc/src/rpc/rtems_rpc.c new file mode 100644 index 0000000..91e2b0f --- /dev/null +++ b/librpc/src/rpc/rtems_rpc.c @@ -0,0 +1,127 @@ +#include "rtems-rpc-config.h" + +/* + * RTEMS multi-tasking support + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/* + * RPC variables for single-thread + */ +static struct _rtems_rpc_task_variables rpc_default = { + -1, /* svc_maxfd */ + {{0}}, /* svc_svc_fdset */ + NULL, /* svc_xports */ + 0, /* svc_xportssize */ + 0, /* svc__svc_fdsetsize */ + 0, /* svc__svc_fdset */ + NULL, /* svc_svc_head */ + 0, /* clnt_perror_buf */ + 0, /* clnt_raw_private */ + 0, /* call_rpc_private */ + 0, /* svc_raw_private */ + + 0, /* svc_simple_proglst */ + 0, /* svc_simple_pl */ + 0, /* svc_simple_transp */ + + 0, /* rpcdname_default_domain */ + 0 /* svc_auths_Auths */ +}; + +/* + * RPC values for initializing a new per-task set of variables + */ +static const struct _rtems_rpc_task_variables rpc_init = { + -1, /* svc_maxfd */ + {{0}}, /* svc_svc_fdset */ + NULL, /* svc_xports */ + 0, /* svc_xportssize */ + 0, /* svc__svc_fdsetsize */ + 0, /* svc__svc_fdset */ + NULL, /* svc_svc_head */ + 0, /* clnt_perror_buf */ + 0, /* clnt_raw_private */ + 0, /* call_rpc_private */ + 0, /* svc_raw_private */ + + 0, /* svc_simple_proglst */ + 0, /* svc_simple_pl */ + 0, /* svc_simple_transp */ + + 0, /* rpcdname_default_domain */ + 0 /* svc_auths_Auths */ +}; + +/* + * Per-task pointer to RPC data + */ +static pthread_once_t rtems_rpc_task_variable_once = PTHREAD_ONCE_INIT; +static pthread_key_t rtems_rpc_task_variable_key; + +/* + * Return the current task variable pointer. + */ +struct _rtems_rpc_task_variables *rtems_rpc_task_variables_get (void) +{ + void *ptr = pthread_getspecific(rtems_rpc_task_variable_key); + if (ptr == NULL) { + ptr = &rpc_default; + } + return (struct _rtems_rpc_task_variables *) ptr; +} + +/* + * Key create function for task_variable_key. + */ +static void rtems_rpc_task_variable_make_key (void) +{ + int eno = pthread_key_create(&rtems_rpc_task_variable_key, NULL); + assert (eno == 0); + /* + * 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) + */ +} + +/* + * Set up per-task RPC variables + */ +int rtems_rpc_task_init (void) +{ + struct _rtems_rpc_task_variables *tvp; + int eno = 0; + + eno = pthread_once( + &rtems_rpc_task_variable_once, + rtems_rpc_task_variable_make_key + ); + assert (eno == 0); + + tvp = pthread_getspecific (rtems_rpc_task_variable_key); + if (tvp == NULL) { + tvp = malloc (sizeof *tvp); + if (tvp == NULL) + return RTEMS_NO_MEMORY; + + eno = pthread_setspecific (rtems_rpc_task_variable_key, (void *) tvp); + if (eno != 0) { + free (tvp); + return RTEMS_INTERNAL_ERROR; + } + *tvp = rpc_init; + } + return RTEMS_SUCCESSFUL; +} diff --git a/librpc/src/rpc/rtime.3 b/librpc/src/rpc/rtime.3 new file mode 100644 index 0000000..ad3e538 --- /dev/null +++ b/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/librpc/src/rpc/rtime.c b/librpc/src/rpc/rtime.c new file mode 100644 index 0000000..4a77084 --- /dev/null +++ b/librpc/src/rpc/rtime.c @@ -0,0 +1,165 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#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( void ); + +#define NYEARS (UINT32_C(1970) - UINT32_C(1900)) +#define TOFFSET (UINT32_C(60)*UINT32_C(60)*UINT32_C(24)*(UINT32_C(365)*NYEARS + (NYEARS/UINT32_C(4)))) + +static void do_close( int ); + +int +rtime( + struct sockaddr_in *addrp, + struct timeval *timep, + struct timeval *timeout ) +{ + int s; + fd_set readfds; + int res; + uint32_t thetime; + struct sockaddr_in from; + socklen_t 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 = _RPC_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(int s) +{ + int save; + + save = errno; + (void)_RPC_close(s); + errno = save; +} diff --git a/librpc/src/rpc/svc.c b/librpc/src/rpc/svc.c new file mode 100644 index 0000000..a1f5769 --- /dev/null +++ b/librpc/src/rpc/svc.c @@ -0,0 +1,502 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifdef HAVE_STRINGS_H +#include /* for ffs */ +#endif +#include +#include +#include +#include +#include + +#define xports (rtems_rpc_task_variables->svc_xports) +#define xportssize (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)(struct svc_req *r, SVCXPRT *xprt); +}; +#define svc_head (rtems_rpc_task_variables->svc_svc_head) + +static struct svc_callout *svc_find(u_long prog, u_long vers, + struct svc_callout **prev); + +/* *************** SVCXPRT related stuff **************** */ + +/* + * Activate a transport handle. + */ +void +xprt_register( + 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( + 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( + SVCXPRT *xprt, + u_long prog, + u_long vers, + void (*dispatch)(struct svc_req *r, SVCXPRT *xprt), + 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( + 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( + 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( + register SVCXPRT *xprt, + xdrproc_t xdr_results, + void *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( + 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( + 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( + 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( + 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( + SVCXPRT *xprt ) +{ + + svcerr_auth(xprt, AUTH_TOOWEAK); +} + +/* + * Program unavailable error reply + */ +void +svcerr_noprog( + 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( + register SVCXPRT *xprt, + rpcvers_t low_vers, + rpcvers_t 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( + int rdfds ) +{ + fd_set readfds; + + FD_ZERO(&readfds); + readfds.fds_bits[0] = rdfds; + svc_getreqset(&readfds); +} + +void +svc_getreqset( + fd_set *readfds ) +{ + svc_getreqset2(readfds, FD_SETSIZE); +} + +void +svc_getreqset2( + 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/librpc/src/rpc/svc_auth.c b/librpc/src/rpc/svc_auth.c new file mode 100644 index 0000000..0bee517 --- /dev/null +++ b/librpc/src/rpc/svc_auth.c @@ -0,0 +1,222 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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 HAVE_CONFIG_H +#include "config.h" +#endif + +#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(struct svc_req *rqst, struct rpc_msg *msg); /* no authentication */ +enum auth_stat _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg); /* (system) unix style (uid, gids) */ +enum auth_stat _svcauth_short(struct svc_req *rqst, struct rpc_msg *msg); /* short hand unix style */ +enum auth_stat _svcauth_des(struct svc_req *rqst, struct rpc_msg *msg); /* des style */ + +/* declarations to allow servers to specify new authentication flavors */ +struct authsvc { + int flavor; + enum auth_stat (*handler)(struct svc_req *rqst, struct rpc_msg *msg); + struct authsvc *next; +}; +#define Auths (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( + 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( + 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( + int cred_flavor, + enum auth_stat (*handler)(struct svc_req *rqst, struct rpc_msg *msg)) +{ + 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/librpc/src/rpc/svc_auth_unix.c b/librpc/src/rpc/svc_auth_unix.c new file mode 100644 index 0000000..0dccc47 --- /dev/null +++ b/librpc/src/rpc/svc_auth_unix.c @@ -0,0 +1,154 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +/* + * Unix longhand authenticator + */ +enum auth_stat +_svcauth_unix( + struct svc_req *rqst, + 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( + struct svc_req *rqst, + struct rpc_msg *msg ) +{ + return (AUTH_REJECTEDCRED); +} diff --git a/librpc/src/rpc/svc_raw.c b/librpc/src/rpc/svc_raw.c new file mode 100644 index 0000000..f3a6f57 --- /dev/null +++ b/librpc/src/rpc/svc_raw.c @@ -0,0 +1,175 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 *)(rtems_rpc_task_variables)->svc_raw_private) + +static bool_t svcraw_recv(SVCXPRT *xprt, struct rpc_msg *msg); +static enum xprt_stat svcraw_stat(SVCXPRT *xprt); +static bool_t svcraw_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static bool_t svcraw_reply(SVCXPRT *xprt, struct rpc_msg *msg); +static bool_t svcraw_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static void svcraw_destroy(SVCXPRT *xprt); + +static struct xp_ops server_ops = { + svcraw_recv, + svcraw_stat, + svcraw_getargs, + svcraw_reply, + svcraw_freeargs, + svcraw_destroy +}; + +SVCXPRT * +svcraw_create(void) +{ + 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(SVCXPRT *xprt) +{ + + return (XPRT_IDLE); +} + +static bool_t +svcraw_recv( + 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( + 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( + 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( + 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(SVCXPRT *xprt) +{ +} diff --git a/librpc/src/rpc/svc_run.c b/librpc/src/rpc/svc_run.c new file mode 100644 index 0000000..fc57fe2 --- /dev/null +++ b/librpc/src/rpc/svc_run.c @@ -0,0 +1,91 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +svc_run(void) +{ + 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/librpc/src/rpc/svc_simple.c b/librpc/src/rpc/svc_simple.c new file mode 100644 index 0000000..9f4b8fd --- /dev/null +++ b/librpc/src/rpc/svc_simple.c @@ -0,0 +1,163 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for PRIxx printf formats */ + +struct prog_lst { + char *(*p_progname)(char *); + rpcprog_t p_prognum; + rpcproc_t p_procnum; + xdrproc_t p_inproc, p_outproc; + struct prog_lst *p_nxt; +}; +static void universal(struct svc_req *, SVCXPRT *); +#define proglst (rtems_rpc_task_variables->svc_simple_proglst) +#define pl (rtems_rpc_task_variables->svc_simple_pl) +#define transp (rtems_rpc_task_variables->svc_simple_transp) + +int +registerrpc( + int prognum, + int versnum, + int procnum, + char *(*progname)(char *), + xdrproc_t inproc, + xdrproc_t outproc ) +{ + + if (procnum == NULLPROC) { + (void) fprintf(stderr, + "can't reassign procedure number %" PRIu32 "\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( + 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, (xdrproc_t) 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 != (xdrproc_t) xdr_void) + /* there was an error */ + return; + if (!svc_sendreply(atransp, lpl->p_outproc, outdata)) { + (void) fprintf(stderr, + "trouble replying to prog %" PRIu32 "\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/librpc/src/rpc/svc_tcp.c b/librpc/src/rpc/svc_tcp.c new file mode 100644 index 0000000..1827d1f --- /dev/null +++ b/librpc/src/rpc/svc_tcp.c @@ -0,0 +1,491 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Ops vector for TCP/IP based rpc service handle + */ +static bool_t svctcp_recv(SVCXPRT *xprt, struct rpc_msg *msg); +static enum xprt_stat svctcp_stat(SVCXPRT *xprt); +static bool_t svctcp_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static bool_t svctcp_reply(SVCXPRT *xprt, struct rpc_msg *msg); +static bool_t svctcp_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static void svctcp_destroy(SVCXPRT *xprt); + +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(SVCXPRT *xprt, struct rpc_msg *msg); +static enum xprt_stat rendezvous_stat(SVCXPRT *xprt); + +static struct xp_ops svctcp_rendezvous_op = { + rendezvous_request, + rendezvous_stat, + (bool_t (*)(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr))abort, + (bool_t (*)(SVCXPRT *xprt, struct rpc_msg *msg))abort, + (bool_t (*)(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr))abort, + svctcp_destroy +}; + +static int readtcp(char *, char*, int), writetcp(char *, char*, int); +static SVCXPRT *makefd_xprt( int fd, u_int sendsize, u_int recvsize); + +struct tcp_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct tcp_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + +/* + * Usage: + * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) tcp based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svctcp_create + * binds it to an arbitrary port. The routine then starts a tcp + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since tcp streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svctcp_create( + int sock, + u_int sendsize, + u_int recvsize) +{ + bool_t madesock = FALSE; + register SVCXPRT *xprt; + register struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t 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)_RPC_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)_RPC_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( + int fd, + u_int sendsize, + u_int recvsize) +{ + + return (makefd_xprt(fd, sendsize, recvsize)); +} + +static SVCXPRT * +makefd_xprt( + int fd, + u_int sendsize, + u_int recvsize) +{ + 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( + SVCXPRT *xprt, + struct rpc_msg *msg) +{ + int sock; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t 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)) { + _RPC_close(sock); + return (FALSE); + } + /* + * The listening socket is in FIONBIO mode and we inherit it. + */ + off = 0; + if (ioctl(sock, FIONBIO, &off) < 0) { + _RPC_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(SVCXPRT *xprt) +{ + + return (XPRT_IDLE); +} + +static void +svctcp_destroy( + SVCXPRT *xprt) +{ + register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1; + + xprt_unregister(xprt); + (void)_RPC_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( + char *_xprt, + char *buf, + int len) +{ + SVCXPRT *xprt = (SVCXPRT*) _xprt; + 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 = _RPC_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( + char *_xprt, + char *buf, + int len) +{ + SVCXPRT *xprt = (SVCXPRT *) _xprt; + register int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) { + if ((i = _RPC_write(xprt->xp_sock, buf, cnt)) < 0) { + ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = + XPRT_DIED; + return (-1); + } + } + return (len); +} + +static enum xprt_stat +svctcp_stat( + SVCXPRT *xprt) +{ + 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( + SVCXPRT *xprt, + 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( + SVCXPRT *xprt, + xdrproc_t xdr_args, + caddr_t args_ptr) +{ + + return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svctcp_freeargs( + SVCXPRT *xprt, + xdrproc_t xdr_args, + caddr_t args_ptr) +{ + 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( + SVCXPRT *xprt, + 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/librpc/src/rpc/svc_udp.c b/librpc/src/rpc/svc_udp.c new file mode 100644 index 0000000..94444c4 --- /dev/null +++ b/librpc/src/rpc/svc_udp.c @@ -0,0 +1,486 @@ +#include "rtems-rpc-config.h" + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#define rpc_buffer(xprt) ((xprt)->xp_p1) + +static bool_t svcudp_recv(SVCXPRT *xprt, struct rpc_msg *msg); +static bool_t svcudp_reply(SVCXPRT *xprt, struct rpc_msg *msg); +static enum xprt_stat svcudp_stat(SVCXPRT *xprt); +static bool_t svcudp_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static bool_t svcudp_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr); +static void svcudp_destroy(SVCXPRT *xprt); +static void cache_set (SVCXPRT *, u_long); +static int cache_get (SVCXPRT *, struct rpc_msg *, char **, u_long *); + +static struct xp_ops svcudp_op = { + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char * su_cache; /* cached data, NULL if no cache */ +}; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate( + int sock, + u_int sendsz, + u_int recvsz ) +{ + bool_t madesock = FALSE; + register SVCXPRT *xprt; + register struct svcudp_data *su; + struct sockaddr_in addr; + socklen_t 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)_RPC_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( + int sock) +{ + + return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE)); +} + +static enum xprt_stat +svcudp_stat( + SVCXPRT *xprt) +{ + + return (XPRT_IDLE); +} + +static bool_t +svcudp_recv( + SVCXPRT *xprt, + struct rpc_msg *msg) +{ + 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( + 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( + SVCXPRT *xprt, + xdrproc_t xdr_args, + caddr_t args_ptr) +{ + + return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); +} + +static bool_t +svcudp_freeargs( + SVCXPRT *xprt, + xdrproc_t xdr_args, + caddr_t args_ptr) +{ + register XDR *xdrs = &(su_data(xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static void +svcudp_destroy( + SVCXPRT *xprt) +{ + register struct svcudp_data *su = su_data(xprt); + + xprt_unregister(xprt); + (void)_RPC_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( + SVCXPRT *transp, + u_long size) +{ + struct svcudp_data *su = su_data(transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) { + CACHE_PERROR("enablecache: cache already enabled"); + return(0); + } + uc = ALLOC(struct udp_cache, 1); + if (uc == NULL) { + CACHE_PERROR("enablecache: could not allocate cache"); + return(0); + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) { + CACHE_PERROR("enablecache: could not allocate cache data"); + return(0); + } + BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC(cache_ptr, size); + if (uc->uc_fifo == NULL) { + CACHE_PERROR("enablecache: could not allocate cache fifo"); + return(0); + } + BZERO(uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return(1); +} + + +/* + * Set an entry in the cache + */ +static void +cache_set( + SVCXPRT *xprt, + u_long replylen) +{ + 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( + 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/librpc/src/xdr/xdr.3 b/librpc/src/xdr/xdr.3 new file mode 100644 index 0000000..c1cdb11 --- /dev/null +++ b/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/librpc/src/xdr/xdr.c b/librpc/src/xdr/xdr.c new file mode 100644 index 0000000..80c29bb --- /dev/null +++ b/librpc/src/xdr/xdr.c @@ -0,0 +1,858 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include + +#if defined(__rtems__) +#define warnx(msg) fprintf(stderr, msg "\n"); +#endif + +/* + * 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 const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free( + xdrproc_t proc, + char *objp) +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(void) +{ + + return (TRUE); +} + + +/* + * XDR integers + */ +bool_t +xdr_int( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 32-bit integers + * same as xdr_u_int32_t - open coded to save a proc call! + */ +bool_t +xdr_int32_t( + 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); + } + /* NOTREACHED */ + 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( + 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 short integers + */ +bool_t +xdr_short( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 16-bit integers + */ +bool_t +xdr_int16_t( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned 16-bit integers + */ +bool_t +xdr_u_int16_t( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char( + 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( + 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( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum( + XDR *xdrs, + enum_t *ep) +{ +#ifndef lint + /* + * enums are treated as ints + */ + if (sizeof (enum_t) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ep)); + } else if (sizeof (enum_t) == sizeof (int)) { + return (xdr_int(xdrs, (int *)ep)); + } else if (sizeof (enum_t) == 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( + XDR *xdrs, + caddr_t cp, + u_int cnt) +{ + 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( + XDR *xdrs, + char **cpp, + u_int *sizep, + u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + 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 = mem_alloc(nodesize); + } + if (sp == NULL) { + warnx("xdr_bytes: out of memory"); + return (FALSE); + } + /* FALLTHROUGH */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj( + 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( + XDR *xdrs, + enum_t *dscmp, /* enum to decide which arm to work on */ + char *unp, /* the union itself */ + const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */ + xdrproc_t dfault) /* default xdr routine */ +{ + 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( + XDR *xdrs, + char **cpp, + u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size = 0; + 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 */ + } + /* FALLTHROUGH */ + case XDR_ENCODE: + size = strlen(sp); + break; + case XDR_DECODE: + 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 = mem_alloc(nodesize); + if (sp == NULL) { + warnx("xdr_string: out of memory"); + return (FALSE); + } + sp[size] = 0; + /* FALLTHROUGH */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring( + XDR *xdrs, + char **cpp) +{ + return xdr_string(xdrs, cpp, LASTUNSIGNED); +} + +/* + * XDR 64-bit integers + */ +bool_t +xdr_int64_t( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR unsigned 64-bit integers + */ +bool_t +xdr_u_int64_t( + 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); + } + /* NOTREACHED */ + return (FALSE); +} + +/* FIXME: RTEMS does not support u_longlong_t and longlong_t, yet */ +#if !defined(__rtems__) +/* + * XDR hypers + */ +bool_t +xdr_hyper(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR unsigned hypers + */ +bool_t +xdr_u_hyper(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} + + +/* + * XDR longlong_t's + */ +bool_t +xdr_longlong_t(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR u_longlong_t's + */ +bool_t +xdr_u_longlong_t(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} +#endif diff --git a/librpc/src/xdr/xdr_array.c b/librpc/src/xdr/xdr_array.c new file mode 100644 index 0000000..190dc3c --- /dev/null +++ b/librpc/src/xdr/xdr_array.c @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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( + 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( + 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/librpc/src/xdr/xdr_float.c b/librpc/src/xdr/xdr_float.c new file mode 100644 index 0000000..b2282b3 --- /dev/null +++ b/librpc/src/xdr/xdr_float.c @@ -0,0 +1,344 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/* + * NB: Not portable. + * This routine works on machines with IEEE754 FP and Vaxen. + */ + +#if defined(__alpha__) || \ + defined(_AM29K) || \ + defined(__arm__) || \ + defined(__epiphany__) || defined(__EPIPHANY__) || \ + defined(__hppa__) || \ + defined(__i386__) || \ + defined(__lm32__) || \ + defined(__m68k__) || defined(__mc68000__) || \ + defined(__mips__) || defined(__moxie__) || \ + defined(__nios2__) || \ + defined(__ns32k__) || \ + defined(__or1k__) || defined(__or1knd__) || \ + defined(__sparc__) || \ + defined(__ppc__) || defined(__PPC__) || \ + defined(__riscv) || \ + defined(__sh__) || \ + defined(__BFIN__) || \ + defined(__m32c__) || \ + defined(__v850) || \ + defined(__x86_64__) + +#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( + 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( + 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/librpc/src/xdr/xdr_mem.c b/librpc/src/xdr/xdr_mem.c new file mode 100644 index 0000000..5b30419 --- /dev/null +++ b/librpc/src/xdr/xdr_mem.c @@ -0,0 +1,245 @@ +/* + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static bool_t xdrmem_getlong_aligned(XDR *xdrs, long *lp); +static bool_t xdrmem_putlong_aligned(XDR *xdrs, const long *lp); +static bool_t xdrmem_getlong_unaligned(XDR *xdrs, long *lp); +static bool_t xdrmem_putlong_unaligned(XDR *xdrs, const long *lp); +static bool_t xdrmem_getbytes(XDR *xdrs, caddr_t addr, u_int len); +static bool_t xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len); +static u_int xdrmem_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */ +static bool_t xdrmem_setpos(XDR *xdrs, u_int pos); +static int32_t *xdrmem_inline_aligned(XDR *xdrs, u_int len); +static int32_t *xdrmem_inline_unaligned(XDR *xdrs, u_int len); +static void xdrmem_destroy(XDR *); + +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( + XDR *xdrs, + char * addr, + u_int size, + enum xdr_op op) +{ + + xdrs->x_op = op; + xdrs->x_ops = ((uintptr_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(XDR *xdrs) +{ + +} + +static bool_t +xdrmem_getlong_aligned( + 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( + XDR *xdrs, + const long *lp) +{ + + if ((xdrs->x_handy -= sizeof(int32_t)) < 0) + return (FALSE); + *(int32_t *)xdrs->x_private = htonl(*lp); + xdrs->x_private += sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_getlong_unaligned( + 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( + XDR *xdrs, + const 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( + XDR *xdrs, + caddr_t addr, + 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( + XDR *xdrs, + const char *addr, + u_int len) +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + memcpy(xdrs->x_private, addr, len); + xdrs->x_private += len; + return (TRUE); +} + +static u_int +xdrmem_getpos( + XDR *xdrs) +{ + + /* XXX w/64-bit pointers, u_int not enough! */ + return ((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_base); +} + +static bool_t +xdrmem_setpos( + XDR *xdrs, + u_int pos) +{ + void *newaddr = xdrs->x_base + pos; + void *lastaddr = xdrs->x_private + xdrs->x_handy; + + if (newaddr > lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (intptr_t)lastaddr - (intptr_t)newaddr; + return (TRUE); +} + +static int32_t * +xdrmem_inline_aligned( + XDR *xdrs, + u_int len) +{ + int32_t *buf = 0; + + if (xdrs->x_handy >= len) { + xdrs->x_handy -= len; + buf = (int32_t *)xdrs->x_private; + xdrs->x_private += len; + } + return (buf); +} + +static int32_t * +xdrmem_inline_unaligned( + XDR *xdrs, + u_int len) +{ + + return (0); +} diff --git a/librpc/src/xdr/xdr_rec.c b/librpc/src/xdr/xdr_rec.c new file mode 100644 index 0000000..7e47527 --- /dev/null +++ b/librpc/src/xdr/xdr_rec.c @@ -0,0 +1,608 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include /* for lseek() */ + +typedef struct rec_strm RECSTREAM; + +static u_int fix_buf_size(u_int); +static bool_t flush_out(RECSTREAM *rstrm, bool_t eor); +static bool_t get_input_bytes(RECSTREAM *rstrm, caddr_t addr, int len); +static bool_t set_input_fragment(RECSTREAM *rstrm); +static bool_t skip_input_bytes(RECSTREAM *rstrm, long cnt); + +static bool_t xdrrec_getlong(XDR *xdrs, long *lp); +static bool_t xdrrec_putlong(XDR *xdrs, const long *lp); +static bool_t xdrrec_getbytes(XDR *xdrs, caddr_t addr, u_int len); +static bool_t xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len); +static u_int xdrrec_getpos(XDR *xdrs); +static bool_t xdrrec_setpos(XDR *xdrs, u_int pos); +static int32_t *xdrrec_inline(XDR *xdrs, u_int len); +static void xdrrec_destroy(XDR *xdrs); + +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)(1L << 31)) + +struct rec_strm { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-goung bits + */ + int (*writeit) (caddr_t, caddr_t, int); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of current fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit) (caddr_t, caddr_t, int); + 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; +}; + + +/* + * 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( + XDR *xdrs, + u_int sendsize, + u_int recvsize, + caddr_t tcp_handle, + int (*readit)(char*, char*, int), /* like read, but pass it a tcp_handle, not sock */ + int (*writeit)(char*, char*, int) /* like write, but pass it a tcp_handle, not sock */ +) +{ + 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; + (uintptr_t)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( + XDR *xdrs, + long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int32_t *buflp = (int32_t *)(rstrm->in_finger); + int32_t mylong; + + /* first try the inline, fast case */ + if ((rstrm->fbtbc >= sizeof(int32_t)) && + (((intptr_t)rstrm->in_boundry - (intptr_t)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( + XDR *xdrs, + const long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + 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( + XDR *xdrs, + caddr_t addr, + u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + 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( + XDR *xdrs, + const char *addr, + u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + long current; + + while (len > 0) { + current = (intptr_t)rstrm->out_boundry - + (intptr_t)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( + XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + long pos; + + pos = lseek((intptr_t)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( + XDR *xdrs, + u_int pos) +{ + 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( + XDR *xdrs, + u_int len) +{ + 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( + XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + + mem_free(rstrm->the_buffer, + rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); + mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); +} + + +/* + * 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( + XDR *xdrs) +{ + 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( + XDR *xdrs) +{ + 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( + XDR *xdrs, + bool_t sendnow) +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent || + ((uintptr_t)rstrm->out_finger + sizeof(u_int32_t) >= + (uintptr_t)rstrm->out_boundry)) { + rstrm->frag_sent = FALSE; + return (flush_out(rstrm, TRUE)); + } + len = (uintptr_t)(rstrm->out_finger) - (uintptr_t)(rstrm->frag_header) - + sizeof(u_int32_t); + *(rstrm->frag_header) = htonl((u_int32_t)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( + RECSTREAM *rstrm, + bool_t eor) +{ + u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0; + u_int32_t len = (uintptr_t)(rstrm->out_finger) - + (uintptr_t)(rstrm->frag_header) - sizeof(u_int32_t); + + *(rstrm->frag_header) = htonl(len | eormask); + len = (uintptr_t)(rstrm->out_finger) - (uintptr_t)(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( + RECSTREAM *rstrm) +{ + caddr_t where; + u_long i; + long len; + + where = rstrm->in_base; + i = (uintptr_t)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( + RECSTREAM *rstrm, + caddr_t addr, + int len) +{ + long current; + + while (len > 0) { + current = (intptr_t)rstrm->in_boundry - (intptr_t)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( + 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( + RECSTREAM *rstrm, + long cnt) +{ + long current; + + while (cnt > 0) { + current = (intptr_t)rstrm->in_boundry - (intptr_t)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( + u_int s) +{ + + if (s < 100) + s = 4000; + return (RNDUP(s)); +} diff --git a/librpc/src/xdr/xdr_reference.c b/librpc/src/xdr/xdr_reference.c new file mode 100644 index 0000000..a2a6ee5 --- /dev/null +++ b/librpc/src/xdr/xdr_reference.c @@ -0,0 +1,142 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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( + 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( + 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/librpc/src/xdr/xdr_sizeof.c b/librpc/src/xdr/xdr_sizeof.c new file mode 100644 index 0000000..72a7ff9 --- /dev/null +++ b/librpc/src/xdr/xdr_sizeof.c @@ -0,0 +1,167 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +/* ARGSUSED */ +static bool_t +x_putlong( + XDR *xdrs, + const long *longp) +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return (TRUE); +} + +/* ARGSUSED */ +static bool_t +x_putbytes( + XDR *xdrs, + const char *bp, + u_int len) +{ + xdrs->x_handy += len; + return (TRUE); +} + +static u_int +x_getpostn( + XDR *xdrs) +{ + return (xdrs->x_handy); +} + +/* ARGSUSED */ +static bool_t +x_setpostn( + XDR *xdrs, + u_int pos) +{ + /* This is not allowed */ + return (FALSE); +} + +static int32_t * +x_inline( + XDR *xdrs, + u_int len) +{ + if (len == 0) { + return (NULL); + } + if (xdrs->x_op != XDR_ENCODE) { + return (NULL); + } + if (len < (intptr_t) 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)((intptr_t) len); + xdrs->x_handy += len; + return ((int32_t *) xdrs->x_private); + } +} + +static int +harmless(void) +{ + /* Always return FALSE/NULL, as the case may be */ + return (0); +} + +static void +x_destroy( + 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( + 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/librpc/src/xdr/xdr_stdio.c b/librpc/src/xdr/xdr_stdio.c new file mode 100644 index 0000000..ca67941 --- /dev/null +++ b/librpc/src/xdr/xdr_stdio.c @@ -0,0 +1,194 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static bool_t xdrstdio_getlong(XDR *xdrs, long *lp); +static bool_t xdrstdio_putlong(XDR *xdrs, const long *lp); +static bool_t xdrstdio_getbytes(XDR *xdrs, caddr_t addr, u_int len); +static bool_t xdrstdio_putbytes(XDR *xdrs, const char *addr, u_int len); +static u_int xdrstdio_getpos(XDR *xdrs); +static bool_t xdrstdio_setpos(XDR *xdrs, u_int pos); +static int32_t *xdrstdio_inline(XDR *xdrs, u_int len); +static void xdrstdio_destroy(XDR *); + +/* + * 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( + 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( + XDR *xdrs) +{ + (void)fflush((FILE *)xdrs->x_private); + /* xx should we close the file ?? */ +} + +static bool_t +xdrstdio_getlong( + XDR *xdrs, + 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( + XDR *xdrs, + const 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( + 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( + XDR *xdrs, + const char *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( + XDR *xdrs) +{ + + return ((u_int) ftell((FILE *)xdrs->x_private)); +} + +static bool_t +xdrstdio_setpos( + XDR *xdrs, + u_int pos) +{ + + return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ? + FALSE : TRUE); +} + +static int32_t * +xdrstdio_inline( + 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/lnetworking.py b/lnetworking.py index 6489b81..5e14e52 100644 --- a/lnetworking.py +++ b/lnetworking.py @@ -31,7 +31,7 @@ import os source_files = [] include_files = {} test_source = [] -exclude_dirs = ['pppd', 'nfsclient', 'testsuites'] +exclude_dirs = ['pppd', 'nfsclient', 'testsuites', 'librpc/include'] exclude_headers = ['rtems-bsd-user-space.h', 'rtems-bsd-kernel-space.h'] for root, dirs, files in os.walk("."): -- cgit v1.2.3