diff options
Diffstat (limited to 'contrib/amd/conf/transp/transp_sockets.c')
-rw-r--r-- | contrib/amd/conf/transp/transp_sockets.c | 540 |
1 files changed, 0 insertions, 540 deletions
diff --git a/contrib/amd/conf/transp/transp_sockets.c b/contrib/amd/conf/transp/transp_sockets.c deleted file mode 100644 index 025e1f3e3cf2..000000000000 --- a/contrib/amd/conf/transp/transp_sockets.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry at Imperial College, London. - * - * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * File: am-utils/conf/transp/transp_sockets.c - * - * Socket specific utilities. - * -Erez Zadok <ezk@cs.columbia.edu> - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amu.h> - - -/* - * find the IP address that can be used to connect to the local host - */ -void -amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost) -{ - struct hostent *hp; - char dq[20]; - -#ifdef DEBUG_off -#error this code is old and probably not useful any longer. -#error Erez, Jan 21, 2004. - struct sockaddr_in sin; - - /* - * Most modern systems should use 127.0.0.1 as the localhost address over - * which you can do NFS mounts. In the past we found that some NFS - * clients may not allow mounts from localhost. So we used - * get_myaddress() and that seemed to work. Alas, on some other systems, - * get_myaddress() may return one of the interface addresses at random, - * and thus use a less efficient IP address than 127.0.0.1. The solution - * is to hard-code 127.0.0.1, but still check if get_myaddress() returns a - * different value and warn about it. - */ - memset((char *) &sin, 0, sizeof(sin)); - get_myaddress(&sin); - if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) - dlog("amu_get_myaddress: myaddress conflict (0x%x vs. 0x%lx)", - sin.sin_addr.s_addr, (u_long) htonl(INADDR_LOOPBACK)); -#endif /* DEBUG_off */ - - if (preferred_localhost == NULL) - goto out; - - /* if specified preferred locahost, then try to use it */ - hp = gethostbyname(preferred_localhost); - if (hp == NULL) { - /* XXX: if hstrerror()/h_errno aren't portable, then need to port the next statement */ - plog(XLOG_ERROR, "Unable to resolve localhost_address \"%s\" (%s): using default", - preferred_localhost, hstrerror(h_errno)); - goto out; - } - if (hp->h_addr_list == NULL) { - plog(XLOG_ERROR, "localhost_address \"%s\" has no IP addresses: using default", - preferred_localhost); - goto out; - } - if (hp->h_addr_list[1] != NULL) { - plog(XLOG_ERROR, "localhost_address \"%s\" has more than one IP addresses: using first", - preferred_localhost); - goto out; - } - memmove((voidp) &iap->s_addr, (voidp) hp->h_addr_list[0], sizeof(iap->s_addr)); - plog(XLOG_INFO, "localhost_address \"%s\" requested, using %s", - preferred_localhost, inet_dquad(dq, sizeof(dq), iap->s_addr)); - return; - - out: - iap->s_addr = htonl(INADDR_LOOPBACK); -} - - -/* - * How to bind to reserved ports. - * Note: if *pp is non-null and is greater than 0, then *pp will not be modified. - */ -int -bind_resv_port(int so, u_short *pp) -{ - struct sockaddr_in sin; - int rc; - u_short port; - - memset((voidp) &sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - - if (pp && *pp > 0) { - sin.sin_port = htons(*pp); - rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); - } else { - port = IPPORT_RESERVED; - - do { - --port; - sin.sin_port = htons(port); - rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); - } while (rc < 0 && (int) port > IPPORT_RESERVED / 2); - - if (pp && rc == 0) - *pp = port; - } - - return rc; -} - - -/* - * close a descriptor, Sockets style - */ -int -amu_close(int fd) -{ - return close(fd); -} - - -/* - * Create an rpc client attached to the mount daemon. - */ -CLIENT * -get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version) -{ - CLIENT *client; - - /* - * First try a TCP socket - */ - if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) { - /* - * Bind to a privileged port - */ - if (bind_resv_port(*sock, (u_short *) 0) < 0) - plog(XLOG_ERROR, "can't bind privileged port (socket)"); - - /* - * Find mountd port to connect to. - * Connect to mountd. - * Create a tcp client. - */ - if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) { - if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0 - && ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL)) - return client; - } - /* - * Failed so close socket - */ - (void) close(*sock); - } /* tcp socket opened */ - /* TCP failed so try UDP */ - if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m"); - *sock = RPC_ANYSOCK; - return NULL; - } - /* - * Bind to a privileged port - */ - if (bind_resv_port(*sock, (u_short *) 0) < 0) - plog(XLOG_ERROR, "can't bind privileged port"); - - /* - * Zero out the port - make sure we recompute - */ - sin->sin_port = 0; - - /* - * Make a UDP client - */ - if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) { - (void) close(*sock); - *sock = RPC_ANYSOCK; - return NULL; - } - dlog("get_mount_client: Using udp, port %d", sin->sin_port); - return client; -} - - -/* - * find the address of the caller of an RPC procedure. - */ -struct sockaddr_in * -amu_svc_getcaller(SVCXPRT *xprt) -{ - /* glibc 2.2 returns a sockaddr_storage ??? */ - return (struct sockaddr_in *) svc_getcaller(xprt); -} - - -/* - * register an RPC server - */ -int -amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, - void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp), - u_long protocol, struct netconfig *dummy) -{ - return svc_register(xprt, prognum, versnum, dispatch, protocol); -} - - -/* - * Create the nfs service for amd - */ -int -create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp)) -{ - - *soNFSp = socket(AF_INET, SOCK_DGRAM, 0); - - if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) { - plog(XLOG_FATAL, "Can't create privileged nfs port (socket)"); - if (*soNFSp >= 0) - close(*soNFSp); - return 1; - } - if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) { - plog(XLOG_FATAL, "cannot create rpc/udp service"); - close(*soNFSp); - return 2; - } - if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) { - plog(XLOG_FATAL, "Can't create privileged nfs port"); - svc_destroy(*nfs_xprtp); - close(*soNFSp); - return 1; - } - if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) { - plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", - (u_long) NFS_PROGRAM, (u_long) NFS_VERSION); - svc_destroy(*nfs_xprtp); - close(*soNFSp); - return 3; - } - - return 0; /* all is well */ -} - - -/* - * Create the amq service for amd (both TCP and UDP) - */ -int -create_amq_service(int *udp_soAMQp, - SVCXPRT **udp_amqpp, - struct netconfig **dummy1, - int *tcp_soAMQp, - SVCXPRT **tcp_amqpp, - struct netconfig **dummy2, - u_short preferred_amq_port) -{ - /* first create TCP service */ - if (tcp_soAMQp) { - *tcp_soAMQp = socket(AF_INET, SOCK_STREAM, 0); - if (*tcp_soAMQp < 0) { - plog(XLOG_FATAL, "cannot create tcp socket for amq service: %m"); - return 1; - } - - /* next, bind to a specific (TCP) port if asked for */ - if (preferred_amq_port > 0) { - /* - * Note: if &preferred_amq_port is non-null and is greater than 0, - * then the pointer will not be modified. We don't want it to be - * modified because it was passed down to create_amq_service as a - * non-pointer (a variable on the stack, not to be modified!) - */ - if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) { - plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port); - return 1; - } - } - - /* now create RPC service handle for amq */ - if (tcp_amqpp && - (*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { - plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp); - return 1; - } - -#ifdef SVCSET_CONNMAXREC - /* - * This is *BSD at its best. - * They just had to do things differently than everyone else - * so they fixed a library DoS issue by forcing client-side changes... - */ -# ifndef RPC_MAXDATASIZE -# define RPC_MAXDATASIZE 9000 -# endif /* not RPC_MAXDATASIZE */ - if (tcp_amqpp) { - int maxrec = RPC_MAXDATASIZE; - SVC_CONTROL(*tcp_amqpp, SVCSET_CONNMAXREC, &maxrec); - } -#endif /* not SVCSET_CONNMAXREC */ - } - - /* next create UDP service */ - if (udp_soAMQp) { - *udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0); - if (*udp_soAMQp < 0) { - plog(XLOG_FATAL, "cannot create udp socket for amq service: %m"); - return 1; - } - - /* next, bind to a specific (UDP) port if asked for */ - if (preferred_amq_port > 0) { - /* - * Note: see comment about using &preferred_amq_port above in this - * function. - */ - if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) { - plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port); - return 1; - } - } - - /* now create RPC service handle for amq */ - if (udp_amqpp && - (*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { - plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp); - return 1; - } - } - - return 0; /* all is well */ -} - - -/* - * Check if the portmapper is running and reachable: 0==down, 1==up - */ -int check_pmap_up(char *host, struct sockaddr_in* sin) -{ - CLIENT *client; - enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */ - int socket = RPC_ANYSOCK; - struct timeval timeout; - - timeout.tv_sec = 2; - timeout.tv_usec = 0; - sin->sin_port = htons(PMAPPORT); - client = clntudp_create(sin, PMAPPROG, PMAPVERS, timeout, &socket); - - if (client == (CLIENT *) NULL) { - plog(XLOG_ERROR, - "check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s", - host, clnt_spcreateerror("")); - return 0; - } - - timeout.tv_sec = 6; - /* Ping the portmapper on a remote system by calling the nullproc */ - clnt_stat = clnt_call(client, - PMAPPROC_NULL, - (XDRPROC_T_TYPE) xdr_void, - NULL, - (XDRPROC_T_TYPE) xdr_void, - NULL, - timeout); - clnt_destroy(client); - close(socket); - sin->sin_port = 0; - - if (clnt_stat == RPC_TIMEDOUT) { - plog(XLOG_ERROR, - "check_pmap_up: failed to contact portmapper on host \"%s\": %s", - host, clnt_sperrno(clnt_stat)); - return 0; - } - return 1; -} - - -/* - * Find the best NFS version for a host and protocol. - */ -u_long -get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto) -{ - CLIENT *clnt; - int again = 0; - enum clnt_stat clnt_stat; - struct timeval tv; - int sock; - char *errstr; - - /* - * If not set or set wrong, then try from NFS_VERS_MAX on down. If - * set, then try from nfs_version on down. - */ - if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) { - nfs_version = NFS_VERS_MAX; - again = 1; - } - tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */ - tv.tv_usec = 0; - -#ifdef HAVE_FS_NFS3 -try_again: -#endif /* HAVE_FS_NFS3 */ - - sock = RPC_ANYSOCK; - errstr = NULL; - if (STREQ(proto, "tcp")) - clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); - else if (STREQ(proto, "udp")) - clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); - else - clnt = NULL; - - if (clnt != NULL) { - /* Try three times (6/2=3) to verify the CLIENT handle. */ - tv.tv_sec = 6; - clnt_stat = clnt_call(clnt, - NFSPROC_NULL, - (XDRPROC_T_TYPE) xdr_void, - 0, - (XDRPROC_T_TYPE) xdr_void, - 0, - tv); - - if (clnt_stat != RPC_SUCCESS) - errstr = clnt_sperrno(clnt_stat); - - close(sock); - clnt_destroy(clnt); - } else { -#ifdef HAVE_CLNT_SPCREATEERROR - errstr = clnt_spcreateerror(""); -#else /* not HAVE_CLNT_SPCREATEERROR */ - errstr = ""; -#endif /* not HAVE_CLNT_SPCREATEERROR */ - } - - if (errstr) { - plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s", - (int) nfs_version, proto, host, errstr); - if (again) { -#ifdef HAVE_FS_NFS3 - if (nfs_version == NFS_VERSION3) { - nfs_version = NFS_VERSION; - again = 0; - plog(XLOG_INFO, "get_nfs_version trying a lower version: NFS(%d,%s)", (int) nfs_version, proto); - } - goto try_again; -#endif /* HAVE_FS_NFS3 */ - } - return 0; - } - - plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s", - (int) nfs_version, proto, host); - return nfs_version; -} - - -#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_PROG) -/* - * Register the autofs service for amd - */ -int -register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *transp)) -{ - int autofs_socket; - SVCXPRT *autofs_xprt = NULL; - - autofs_socket = socket(AF_INET, SOCK_DGRAM, 0); - - if (autofs_socket < 0 || bind_resv_port(autofs_socket, NULL) < 0) { - plog(XLOG_FATAL, "Can't create privileged autofs port (socket)"); - return 1; - } - if ((autofs_xprt = svcudp_create(autofs_socket)) == NULL) { - plog(XLOG_FATAL, "Can't create autofs rpc/udp service"); - return 2; - } - if (autofs_xprt->xp_port >= IPPORT_RESERVED) { - plog(XLOG_FATAL, "Can't create privileged autofs port"); - return 1; - } - if (!svc_register(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_dispatch, 0)) { - plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", - (u_long) AUTOFS_PROG, (u_long) AUTOFS_VERS); - return 3; - } - - return 0; /* all is well */ -} - - -int -unregister_autofs_service(char *autofs_conftype) -{ - svc_unregister(AUTOFS_PROG, AUTOFS_VERS); - return 0; -} -#endif /* HAVE_FS_AUTOFS && AUTOFS_PROG */ |